diff --git a/.gitignore b/.gitignore index caec0976..9db77445 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ $RECYCLE.BIN/ *.log log.txt mealmaestro-logs.txt +logs/ # ios diff --git a/backend/build.gradle b/backend/build.gradle index 2cf073f5..d936900e 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -26,7 +26,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-logging' - implementation 'org.seleniumhq.selenium:selenium-java:4.12.1' implementation 'org.jsoup:jsoup:1.16.1' implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' diff --git a/backend/src/main/java/fellowship/mealmaestro/config/GlobalExceptionHandler.java b/backend/src/main/java/fellowship/mealmaestro/config/GlobalExceptionHandler.java index 5042f310..bdb1a7ec 100644 --- a/backend/src/main/java/fellowship/mealmaestro/config/GlobalExceptionHandler.java +++ b/backend/src/main/java/fellowship/mealmaestro/config/GlobalExceptionHandler.java @@ -5,12 +5,13 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import fellowship.mealmaestro.config.exceptions.UserNotFoundException; + @RestControllerAdvice public class GlobalExceptionHandler { - // @ExceptionHandler(RuntimeException.class) - // public ResponseEntity handleUserNotFoundException(RuntimeException e) - // { - // return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND); - // } + @ExceptionHandler(UserNotFoundException.class) + public ResponseEntity handleUserNotFoundException(UserNotFoundException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND); + } } diff --git a/backend/src/main/java/fellowship/mealmaestro/config/Neo4jConfig.java b/backend/src/main/java/fellowship/mealmaestro/config/Neo4jConfig.java index f5ac5198..5501a7e6 100644 --- a/backend/src/main/java/fellowship/mealmaestro/config/Neo4jConfig.java +++ b/backend/src/main/java/fellowship/mealmaestro/config/Neo4jConfig.java @@ -38,7 +38,7 @@ public Driver neo4jDriver() { username = "No DB Username Found"; password = "No DB Password Found"; } - + return GraphDatabase.driver(uri, AuthTokens.basic(username, password)); } } \ No newline at end of file diff --git a/backend/src/main/java/fellowship/mealmaestro/config/SecurityConfig.java b/backend/src/main/java/fellowship/mealmaestro/config/SecurityConfig.java index e2066b59..29f2f32f 100644 --- a/backend/src/main/java/fellowship/mealmaestro/config/SecurityConfig.java +++ b/backend/src/main/java/fellowship/mealmaestro/config/SecurityConfig.java @@ -22,34 +22,31 @@ public class SecurityConfig { private final AuthenticationProvider authenticationProvider; - public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter, AuthenticationProvider authenticationProvider){ + public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter, AuthenticationProvider authenticationProvider) { this.jwtAuthFilter = jwtAuthFilter; this.authenticationProvider = authenticationProvider; } - + @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http - .cors(cors -> cors.configurationSource(corsConfigurationSource())) - .csrf(csrf -> csrf.disable()) - .authorizeHttpRequests(authReq -> authReq - .requestMatchers("/register", "/authenticate") - .permitAll() - .anyRequest() - .authenticated() - ) - .sessionManagement(session -> session - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - ) - .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); - + .cors(cors -> cors.configurationSource(corsConfigurationSource())) + .csrf(csrf -> csrf.disable()) + .authorizeHttpRequests(authReq -> authReq + .requestMatchers("/register", "/authenticate", "/hello") + .permitAll() + .anyRequest() + .authenticated()) + .sessionManagement(session -> session + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); http.authenticationProvider(authenticationProvider); return http.build(); } @Bean - CorsConfigurationSource corsConfigurationSource(){ + CorsConfigurationSource corsConfigurationSource() { CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setAllowedOrigins(Arrays.asList("*")); corsConfig.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); diff --git a/backend/src/main/java/fellowship/mealmaestro/config/exceptions/UserNotFoundException.java b/backend/src/main/java/fellowship/mealmaestro/config/exceptions/UserNotFoundException.java new file mode 100644 index 00000000..8c8aa3d9 --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/config/exceptions/UserNotFoundException.java @@ -0,0 +1,7 @@ +package fellowship.mealmaestro.config.exceptions; + +public class UserNotFoundException extends RuntimeException { + public UserNotFoundException(String message) { + super(message); + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/controllers/LikeDislikeController.java b/backend/src/main/java/fellowship/mealmaestro/controllers/LikeDislikeController.java new file mode 100644 index 00000000..398ffd61 --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/controllers/LikeDislikeController.java @@ -0,0 +1,42 @@ +package fellowship.mealmaestro.controllers; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import fellowship.mealmaestro.models.neo4j.MealModel; +import jakarta.validation.Valid; + +@RestController +public class LikeDislikeController { + + public LikeDislikeController() { + + } + + @PostMapping("/liked") + public ResponseEntity liked(@Valid @RequestBody MealModel request, @RequestHeader("Authorization") String token) { + if (token == null || token.isEmpty()) { + return ResponseEntity.badRequest().build(); + } + + String authToken = token.substring(7); + //service here + + return ResponseEntity.ok().build(); + } + + @PostMapping("/disliked") + public ResponseEntity disliked(@Valid @RequestBody MealModel request, @RequestHeader("Authorization") String token) { + if (token == null || token.isEmpty()) { + return ResponseEntity.badRequest().build(); + } + + String authToken = token.substring(7); + //service here + + return ResponseEntity.ok().build(); + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/controllers/MealManagementController.java b/backend/src/main/java/fellowship/mealmaestro/controllers/MealManagementController.java index 6451f0c5..b713bb31 100644 --- a/backend/src/main/java/fellowship/mealmaestro/controllers/MealManagementController.java +++ b/backend/src/main/java/fellowship/mealmaestro/controllers/MealManagementController.java @@ -18,19 +18,27 @@ import fellowship.mealmaestro.models.RegenerateMealRequest; import fellowship.mealmaestro.models.neo4j.DateModel; import fellowship.mealmaestro.models.neo4j.MealModel; +import fellowship.mealmaestro.services.LogService; import fellowship.mealmaestro.services.MealDatabaseService; import fellowship.mealmaestro.services.MealManagementService; +import fellowship.mealmaestro.services.RecommendationService; import jakarta.validation.Valid; @RestController public class MealManagementController { + private final MealManagementService mealManagementService; private final MealDatabaseService mealDatabaseService; + private final RecommendationService recommendationService; + private final LogService logService; public MealManagementController(MealManagementService mealManagementService, - MealDatabaseService mealDatabaseService) { + MealDatabaseService mealDatabaseService, RecommendationService recommendationService, + LogService logService) { this.mealManagementService = mealManagementService; this.mealDatabaseService = mealDatabaseService; + this.recommendationService = recommendationService; + this.logService = logService; } @PostMapping("/getMealPlanForDay") @@ -123,13 +131,26 @@ public ResponseEntity regenerate(@RequestBody RegenerateMealRequest r @RequestHeader("Authorization") String token) throws JsonMappingException, JsonProcessingException { - token = token.substring(7); + logService.logMeal(token, request.getMeal(), "regenerate"); + MealModel recoMeal = null; + try { + recoMeal = recommendationService.getRecommendedMeal(request.getMeal().getType(), token); + } catch (Exception e) { + System.out.println(e); + } - // Try find an appropriate meal in the database - Optional replacementMeal = mealDatabaseService.findMealTypeForUser(request.getMeal().getType(), - token); + Optional replacementMeal = null; MealModel returnedMeal = null; + if (recoMeal != null) { + replacementMeal = Optional.ofNullable(recoMeal); + } else { + token = token.substring(7); + + // Try find an appropriate meal in the database + replacementMeal = mealDatabaseService.findMealTypeForUser(request.getMeal().getType(), token); + } + if (replacementMeal.isPresent()) { returnedMeal = mealDatabaseService.replaceMeal(request, replacementMeal.get(), token); } else { @@ -141,16 +162,4 @@ public ResponseEntity regenerate(@RequestBody RegenerateMealRequest r return ResponseEntity.ok(returnedMeal); } - // @GetMapping("/getPopularMeals") - // public String popularMeals() throws JsonMappingException, - // JsonProcessingException{ - // return mealManagementService.generatePopularMeals(); - // } - - // @GetMapping("/getSearchedMeals") - // public String searchedMeals(@RequestParam String query) throws - // JsonMappingException, JsonProcessingException { - // // Call the mealManagementService to search meals based on the query - // return mealManagementService.generateSearchedMeals(query); - // } } diff --git a/backend/src/main/java/fellowship/mealmaestro/controllers/ProductController.java b/backend/src/main/java/fellowship/mealmaestro/controllers/ProductController.java index 5ce7df21..22251ea4 100644 --- a/backend/src/main/java/fellowship/mealmaestro/controllers/ProductController.java +++ b/backend/src/main/java/fellowship/mealmaestro/controllers/ProductController.java @@ -36,4 +36,4 @@ public ResponseEntity addProduct(@RequestBody FoodModelM product, } return ResponseEntity.ok(barcodeService.addProduct(product)); } -} \ No newline at end of file +} diff --git a/backend/src/main/java/fellowship/mealmaestro/controllers/RecipeBookController.java b/backend/src/main/java/fellowship/mealmaestro/controllers/RecipeBookController.java index 69c64210..131eb55e 100644 --- a/backend/src/main/java/fellowship/mealmaestro/controllers/RecipeBookController.java +++ b/backend/src/main/java/fellowship/mealmaestro/controllers/RecipeBookController.java @@ -1,9 +1,11 @@ package fellowship.mealmaestro.controllers; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import fellowship.mealmaestro.models.neo4j.MealModel; +import fellowship.mealmaestro.services.LogService; import fellowship.mealmaestro.services.RecipeBookService; import jakarta.validation.Valid; @@ -11,7 +13,8 @@ @RestController public class RecipeBookController { - + @Autowired + private LogService logService; private final RecipeBookService recipeBookService; public RecipeBookController(RecipeBookService recipeBookService) { @@ -25,6 +28,8 @@ public ResponseEntity addRecipe(@Valid @RequestBody MealModel request return ResponseEntity.badRequest().build(); } + logService.logMeal(token, request, "save"); + String authToken = token.substring(7); return ResponseEntity.ok(recipeBookService.addRecipe(request, authToken)); } diff --git a/backend/src/main/java/fellowship/mealmaestro/controllers/UserController.java b/backend/src/main/java/fellowship/mealmaestro/controllers/UserController.java index ed17d8a7..16414a49 100644 --- a/backend/src/main/java/fellowship/mealmaestro/controllers/UserController.java +++ b/backend/src/main/java/fellowship/mealmaestro/controllers/UserController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; +import fellowship.mealmaestro.config.exceptions.UserNotFoundException; import fellowship.mealmaestro.models.UpdateUserRequestModel; import fellowship.mealmaestro.models.auth.AuthenticationRequestModel; import fellowship.mealmaestro.models.auth.AuthenticationResponseModel; @@ -32,7 +33,7 @@ public UserController(AuthenticationService authenticationService, UserService u @PostMapping("/findByEmail") public UserModel findByEmail(@RequestBody UserModel user) { - return userService.findByEmail(user.getEmail()).orElseThrow(() -> new RuntimeException("User not found")); + return userService.findByEmail(user.getEmail()).orElseThrow(() -> new UserNotFoundException("User not found")); } @PostMapping("/register") diff --git a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/MealModel.java b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/MealModel.java index 7463f03d..142051b3 100644 --- a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/MealModel.java +++ b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/MealModel.java @@ -13,7 +13,7 @@ public class MealModel { private String name; @NotBlank(message = "An image is required") - private String image; + private String image = "https://images.unsplash.com/photo-1498837167922-ddd27525d352?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80"; @NotBlank(message = "A Description is required") private String description; @@ -37,7 +37,7 @@ public MealModel(String name, String instructions, String description, String im this.name = name; this.instructions = instructions; this.description = description; - this.image = image; + this.image = "https://images.unsplash.com/photo-1498837167922-ddd27525d352?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80"; this.ingredients = ingredients; this.cookingTime = cookingTime; } diff --git a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/PantryModel.java b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/PantryModel.java index 0cce95da..5631efb5 100644 --- a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/PantryModel.java +++ b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/PantryModel.java @@ -45,4 +45,12 @@ public String toString() { return csv; } + + public List getNameList() throws Exception{ + List list = new ArrayList<>(); + for (FoodModel foodModel : this.foods) { + list.add(foodModel.getName()); + } + return list; + } } diff --git a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/UserModel.java b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/UserModel.java index 8da39dbb..83a25ec5 100644 --- a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/UserModel.java +++ b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/UserModel.java @@ -12,6 +12,7 @@ import org.springframework.security.core.userdetails.UserDetails; import fellowship.mealmaestro.models.auth.AuthorityRoleModel; +import fellowship.mealmaestro.models.neo4j.relationships.HasLogEntry; import fellowship.mealmaestro.models.neo4j.relationships.HasMeal; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; @@ -54,6 +55,36 @@ public class UserModel implements UserDetails { @Relationship(type = "HAS_MEAL") private List meals; + @Relationship(type = "HAS_LOG_ENTRY") + private List entries; + + @Relationship(type = "HAS_VIEW") + private ViewModel view; + + public Long getVersion() { + return this.version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public List getEntries() { + return this.entries; + } + + public void setEntries(List entries) { + this.entries = entries; + } + + public ViewModel getView() { + return this.view; + } + + public void setView(ViewModel view) { + this.view = view; + } + public UserModel() { this.authorityRole = AuthorityRoleModel.USER; } @@ -167,4 +198,12 @@ public List getMeals() { public void setMeals(List meals) { this.meals = meals; } + + public List getLogEntries() { + return entries; + } + + public void setLogEntries(List entries) { + this.entries = entries; + } } diff --git a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/ViewModel.java b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/ViewModel.java new file mode 100644 index 00000000..ae2cf15b --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/ViewModel.java @@ -0,0 +1,144 @@ +package fellowship.mealmaestro.models.neo4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.data.neo4j.core.schema.GeneratedValue; +import org.springframework.data.neo4j.core.schema.Id; +import org.springframework.data.neo4j.core.schema.Node; + +@Node("View") +public class ViewModel { + + @Id + @GeneratedValue + private Long id; + + private String[] Keys; + private List scoreValues; + private List nScoreValues; + + private Double max = Double.MIN_VALUE; + private Double min = Double.MAX_VALUE; + + public ViewModel() { + } + + + public HashMap getScoreMap() { + return arraysToHashMap(Keys, nScoreValues); + } + + + public void updateScore(String ingredient, Double Score) { + HashMap ScoreMap = new HashMap<>(); + HashMap nScoreMap = new HashMap<>(); + + if(Keys != null){ + ScoreMap = arraysToHashMap(Keys, scoreValues); + nScoreMap = arraysToHashMap(Keys, nScoreValues); + } + + + if (ScoreMap.containsKey(ingredient)) { + Boolean changed = false; + Double score = ScoreMap.get(ingredient); + Double nScore = nScoreMap.get(ingredient); + score += Score; + if (score > max || max == null) { + max = score; + changed = true; + } + + if (score < min || min == null) { + min = score; + changed = true; + } + nScore = normalise(Score); + if (changed) { + normalise(); + } + + ScoreMap.put(ingredient, score); + nScoreMap.put(ingredient, nScore); + + } else { + + ScoreMap.put(ingredient, Score); + nScoreMap.put(ingredient, normalise(Score)); + } + Keys = hashMapKeysToArray(nScoreMap); + scoreValues = hashMapValuesToArray(ScoreMap); + nScoreValues = hashMapValuesToArray(nScoreMap); + } + + public Double normalise(Double Score) { + return 2 * ((Score - min) / (max - min)) - 1; + + } + + public void normalise() { + // return 2 * ((Score - min) / (max - min)) - 1; + this.max = Double.MIN_VALUE; + this.min = Double.MAX_VALUE; + for (Double score : scoreValues) { + if(score < this.min){ + this.min = score; + } + if(score > this.max){ + this.max = score; + } + } + HashMap ScoreMap = new HashMap<>(); + HashMap nScoreMap = new HashMap<>(); + for (String ingredient : ScoreMap.keySet()) { + nScoreMap.put(ingredient, 2 * ((ScoreMap.get(ingredient) - min) / (max - min)) - 1); + } + Keys = hashMapKeysToArray(nScoreMap); + scoreValues = hashMapValuesToArray(ScoreMap); + nScoreValues = hashMapValuesToArray(nScoreMap); + } + + public static List hashMapValuesToArray(HashMap hashMap) { + List listFromHashMap = new ArrayList<>(); + for (Map.Entry entry : hashMap.entrySet()) { + Double value = entry.getValue(); + listFromHashMap.add(value); + } + return listFromHashMap; + } + + public static String[] hashMapKeysToArray(HashMap hashMap) { + return hashMap.keySet().toArray(new String[0]); + } + + public static HashMap arraysToHashMap(String[] keys, List nScoreValues2) { + if (keys.length != nScoreValues2.size()) { + throw new IllegalArgumentException("Keys and values arrays must have the same length."); + } + + HashMap hashMap = new HashMap<>(); + for (int i = 0; i < keys.length; i++) { + hashMap.put(keys[i], nScoreValues2.get(i)); + } + return hashMap; + } + + public List getPositiveNScores(Double minNValue) throws Exception{ + ListKeys = new ArrayList<>(); + if(this.Keys != null && this.Keys.length > 0){ + HashMap nScoreMap = arraysToHashMap(this.Keys, this.nScoreValues); + + for (Map.Entry entry : nScoreMap.entrySet()) { + if (entry.getValue() >= minNValue) { + Keys.add(entry.getKey()); + } + } + + return Keys; + } + else return null; + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/models/neo4j/relationships/HasLogEntry.java b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/relationships/HasLogEntry.java new file mode 100644 index 00000000..c5315bad --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/models/neo4j/relationships/HasLogEntry.java @@ -0,0 +1,79 @@ +package fellowship.mealmaestro.models.neo4j.relationships; + +import java.time.LocalDate; + +import org.springframework.data.neo4j.core.schema.GeneratedValue; +import org.springframework.data.neo4j.core.schema.Id; +import org.springframework.data.neo4j.core.schema.RelationshipProperties; +import org.springframework.data.neo4j.core.schema.TargetNode; + +import fellowship.mealmaestro.models.neo4j.MealModel; + +@RelationshipProperties +public class HasLogEntry { + @Id + @GeneratedValue + private Long id; + + @TargetNode + private MealModel meal; + + private LocalDate date; + + private String entryType; + + private boolean processed; + + public boolean isProcessed() { + return this.processed; + } + + public boolean getProcessed() { + return this.processed; + } + + public void setProcessed(boolean processed) { + this.processed = processed; + } + + public HasLogEntry() { + } + + public HasLogEntry(MealModel meal, LocalDate date, String entryType) { + this.meal = meal; + this.date = date; + this.entryType = entryType; + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public MealModel getMeal() { + return this.meal; + } + + public void setMeal(MealModel meal) { + this.meal = meal; + } + + public LocalDate getDate() { + return this.date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getEntryType() { + return this.entryType; + } + + public void setEntryType(String entryType) { + this.entryType = entryType; + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/repositories/neo4j/UserRepository.java b/backend/src/main/java/fellowship/mealmaestro/repositories/neo4j/UserRepository.java index 63492a05..67ee04d8 100644 --- a/backend/src/main/java/fellowship/mealmaestro/repositories/neo4j/UserRepository.java +++ b/backend/src/main/java/fellowship/mealmaestro/repositories/neo4j/UserRepository.java @@ -1,11 +1,13 @@ package fellowship.mealmaestro.repositories.neo4j; +import java.util.List; import java.util.Optional; import org.springframework.data.neo4j.repository.Neo4jRepository; import org.springframework.data.neo4j.repository.query.Query; import fellowship.mealmaestro.models.neo4j.UserModel; +import fellowship.mealmaestro.models.neo4j.relationships.HasLogEntry; public interface UserRepository extends Neo4jRepository { @@ -13,4 +15,10 @@ public interface UserRepository extends Neo4jRepository { @Query("MATCH (n0:User {email: $email}) SET n0.name = $name RETURN n0") UserModel updateUser(String email, String username); + + @Query("MATCH (u:User)-[r:HAS_LOG_ENTRY]->(logEntry) WHERE r.processed IS NULL OR NOT r.processed RETURN DISTINCT u") + List findUsersWithNewLogEntries(); + + @Query("MATCH (user:User {id: $user.id})-[:HAS_LOG_ENTRY]->(logEntry) WHERE NOT logEntry.processed RETURN logEntry") + List findUnprocessedLogEntriesForUser(UserModel user); } diff --git a/backend/src/main/java/fellowship/mealmaestro/services/HydrationService.java b/backend/src/main/java/fellowship/mealmaestro/services/HydrationService.java new file mode 100644 index 00000000..f0609c96 --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/services/HydrationService.java @@ -0,0 +1,98 @@ +package fellowship.mealmaestro.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import fellowship.mealmaestro.models.neo4j.UserModel; +import fellowship.mealmaestro.models.neo4j.ViewModel; +import fellowship.mealmaestro.models.neo4j.relationships.HasLogEntry; +import fellowship.mealmaestro.repositories.neo4j.UserRepository; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class HydrationService { + @Autowired + private UserRepository userRepository; + + @Transactional + @Scheduled(fixedRate = 1 * 60 * 1000) + public void pollLogs() { + List userList = userRepository.findUsersWithNewLogEntries(); + // per user + for (UserModel nuser : userList) { + UserModel user = userRepository.findByEmail(nuser.getEmail()).get(); + ViewModel viewModel = user.getView(); + if (viewModel == null) { + viewModel = new ViewModel(); + } + for (int i = 0; i < user.getEntries().size(); i++) { + HasLogEntry entry = user.getEntries().remove(i); + String ingredientString = entry.getMeal().getIngredients(); + // trim ingredient list + ingredientString = trimCharacters(ingredientString); + // convert to List + List ingredientList = parseCommaSeparatedString(ingredientString); + // Scores ++ * multiplier + Double S_MULTIPLIER = getScoreValue(entry.getEntryType()); + + // update view model + for (String ingredient : ingredientList) { + viewModel.updateScore(ingredient, S_MULTIPLIER); + } + + // set processed + entry.setProcessed(true); + user.getEntries().add(entry); + } + user.setView(viewModel); + userRepository.save(user); + } + + } + + // helper functions to be done + // trim + private static String trimCharacters(String input) { + String regex = "\\d+(?:/\\d+)?(?:\\s*(?:tablespoon|tablespoons|teaspoon|teaspoons|cup|cups|ounce|ounces|gram|grams|milliliter|milliliters|liter|liters|pound|pounds|kg|kilo|kilogram|kilograms|gallon|gallons))?"; + String result = input.replaceAll(regex, ""); + return result.toLowerCase(); + } + + // convert + private static List parseCommaSeparatedString(String input) { + // return Arrays.asList(input.split(",")); + String[] elements = input.split(","); + + List result = new ArrayList<>(); + for (String element : elements) { + result.add(element.trim()); + } + + return result; + } + + // scores + private static Double getScoreValue(String entryType) { + switch (entryType.toLowerCase()) { + case "regenerated": + return -0.2; + + case "like": + return 1.0; + + case "dislike": + return -0.5; + + case "save": + return 0.7; + + default: + return 0.5; + + } + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/services/LogService.java b/backend/src/main/java/fellowship/mealmaestro/services/LogService.java new file mode 100644 index 00000000..d0bd4371 --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/services/LogService.java @@ -0,0 +1,45 @@ +package fellowship.mealmaestro.services; + +import java.time.LocalDate; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import fellowship.mealmaestro.models.neo4j.MealModel; +import fellowship.mealmaestro.models.neo4j.UserModel; +import fellowship.mealmaestro.models.neo4j.relationships.HasLogEntry; +import fellowship.mealmaestro.models.neo4j.relationships.HasMeal; +import fellowship.mealmaestro.repositories.neo4j.UserRepository; + +@Service +public class LogService { + @Autowired + private UserService userService; + @Autowired + private UserRepository userRepository; + @Transactional + public void logMeal(String token, MealModel meal, String entryType) { + UserModel user = userService.getUser(token); + MealModel dbMeal = null; + for (HasMeal m : user.getMeals()) { + if (m.getMeal().getName().equals(meal.getName())) { + dbMeal = m.getMeal(); + } + } + if (dbMeal == null) { + System.out.println("logging failed"); + return; + } + HasLogEntry entry = new HasLogEntry(dbMeal, LocalDate.now(), entryType); + user.getEntries().add(entry); + userRepository.save(user); + System.out.println("LogEntry saved! (" + meal.getName() + "," + entryType + ")"); + + } + + public List findUnprocessedLogEntriesForUser(UserModel user) { + return userRepository.findUnprocessedLogEntriesForUser(user); + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/services/MealDatabaseService.java b/backend/src/main/java/fellowship/mealmaestro/services/MealDatabaseService.java index 1e1460f9..1aca1c76 100644 --- a/backend/src/main/java/fellowship/mealmaestro/services/MealDatabaseService.java +++ b/backend/src/main/java/fellowship/mealmaestro/services/MealDatabaseService.java @@ -138,6 +138,44 @@ public Optional findMealTypeForUser(String type, String token) { return Optional.empty(); } + public Optional findMealForUser(String mealName, String token) { + String email = jwtService.extractUserEmail(token); + + UserModel user = userRepository.findByEmail(email).get(); + List randomMeals = mealRepository.get100RandomMeals(); + + // if meal with meal type is present in randomMeals, return it + for (MealModel meal : randomMeals) { + if (meal.getName().equals(mealName)) { + if (canMakeMeal(user.getPantry().getFoods(), meal.getIngredients())) { + return Optional.of(meal); + } + } + } + + return Optional.empty(); + } + + public Optional findMealUserLikes(String type, String token, String likedAndAvailableIngredients) { + String email = jwtService.extractUserEmail(token); + + UserModel user = userRepository.findByEmail(email).get(); + List randomMeals = mealRepository.get100RandomMeals(); + + // if meal with meal type is present in randomMeals, return it + for (MealModel meal : randomMeals) { + if (meal.getType().equals(type)) { + if (canMakeMeal(user.getPantry().getFoods(), meal.getIngredients())) + //% matched + if(mealPercentageMatched(likedAndAvailableIngredients, meal.getIngredients())) + { + return Optional.of(meal); + } + } + } + + return Optional.empty(); + } public boolean canMakeMeal(List pantryItems, String ingredients) { String[] ingredientsArray = ingredients.split(","); @@ -156,6 +194,28 @@ public boolean canMakeMeal(List pantryItems, String ingredients) { return true; } + private final Double PERCENTAGE_TO_MATCH = 0.4; + + public boolean mealPercentageMatched(String likedIngredients, String mealIngredients) { + String[] likedIngredientsArray = likedIngredients.split(","); + String[] mealIngredientsArray = mealIngredients.split(","); + int totalLikedIngredients = likedIngredientsArray.length; + int matchingIngredientsCount = 0; + + for (String likedIngredient : likedIngredientsArray) { + for (String mealIngredient : mealIngredientsArray) { + if (mealIngredient.trim().equalsIgnoreCase(likedIngredient.trim())) { + matchingIngredientsCount++; + break; + } + } + } + + double percentageMatched = (double) matchingIngredientsCount / totalLikedIngredients; + + return percentageMatched >= PERCENTAGE_TO_MATCH; + } + @Transactional public MealModel replaceMeal(RegenerateMealRequest request, MealModel newMeal, String token) { String email = jwtService.extractUserEmail(token); diff --git a/backend/src/main/java/fellowship/mealmaestro/services/MealManagementService.java b/backend/src/main/java/fellowship/mealmaestro/services/MealManagementService.java index 2ce340f5..c25a5d0a 100644 --- a/backend/src/main/java/fellowship/mealmaestro/services/MealManagementService.java +++ b/backend/src/main/java/fellowship/mealmaestro/services/MealManagementService.java @@ -50,6 +50,41 @@ public MealModel generateMeal(String mealType, String token) { String imageUrl = ""; imageUrl = unsplashService.fetchPhoto(mealJson.get("name").asText()); + if (!imageUrl.contains(("https://"))) + imageUrl = "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=640&q=80"; + + ObjectNode mealObject = objectMapper.valueToTree(mealJson); + mealObject.put("type", mealType); + mealObject.put("image", imageUrl); + + MealModel mealModel = objectMapper.treeToValue(mealObject, MealModel.class); + return mealModel; + } catch (JsonProcessingException e) { + System.out.println(e.getMessage()); + return defaultMeal; + } + } + + public MealModel generateMealFromIngredients(String mealType, String availableIngredients, String token) throws IOException { + MealModel defaultMeal = new MealModel("Bread", "1. Toast the bread", "Delicious Bread", + "https://images.unsplash.com/photo-1598373182133-52452f7691ef?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80", + "Bread", "5 minutes"); + defaultMeal.setType("breakfast"); + try { + JsonNode mealJson = objectMapper.readTree(openaiApiService.fetchMealResponseFromIngredients(mealType, availableIngredients, token)); + int i = 0; + if (!validate(mealJson)) { + for (i = 0; i < 4; i++) { + mealJson = objectMapper.readTree(openaiApiService.fetchMealResponseFromIngredients(mealType, availableIngredients,token)); + if (validate(mealJson)) + break; + } + return defaultMeal; + } + + String imageUrl = ""; + imageUrl = unsplashService.fetchPhoto(mealJson.get("name").asText()); + ObjectNode mealObject = objectMapper.valueToTree(mealJson); mealObject.put("type", mealType); mealObject.put("image", imageUrl); diff --git a/backend/src/main/java/fellowship/mealmaestro/services/OpenaiApiService.java b/backend/src/main/java/fellowship/mealmaestro/services/OpenaiApiService.java index 300d4662..796d0f4d 100644 --- a/backend/src/main/java/fellowship/mealmaestro/services/OpenaiApiService.java +++ b/backend/src/main/java/fellowship/mealmaestro/services/OpenaiApiService.java @@ -104,7 +104,76 @@ public String getJSONResponse(String Type, String token) throws JsonProcessingEx .body(Mono.just(jsonRequest), String.class) .retrieve() .bodyToMono(String.class) - .timeout(Duration.ofSeconds(10)) + .timeout(Duration.ofSeconds(30)) + .block(); + + return response; + } catch (RuntimeException e) { + if (e.getCause() instanceof TimeoutException) { + System.out.println("Timeout"); + return "Timeout"; + } else { + System.out.println("Error"); + return "Error"; + } + } + } + + public String fetchMealResponseFromIngredients(String type, String availableIngredients, String token)throws JsonMappingException, JsonProcessingException { + + String jsonResponse = getJSONResponse(type, token); + if (jsonResponse.equals("Timeout")) { + jsonResponse = getJSONResponse(type, token); + } + if (jsonResponse.equals("Error") || jsonResponse.equals("Timeout")) { + return "{\"error\":\"error\"}"; + } + + JsonNode jsonNode = jsonMapper.readTree(jsonResponse); + + JsonNode contentNode = jsonNode + .path("choices") + .get(0) + .path("message") + .path("content"); + + String text = contentNode.asText(); + + text = text.replace("\\\"", "\""); + text = text.replace("\n", ""); + text = text.replace("/r/n", "\\r\\n"); + int index = text.indexOf('{'); + int lastIndex = text.lastIndexOf('}') + 1; + if (index != -1 && lastIndex != -1 && index < lastIndex) { + text = text.substring(index, lastIndex); + } + + return text; + } + + public String getJSONResponse(String Type, String token, String availableIngredients) throws JsonProcessingException { + + OpenAIChatRequest prompt; + String jsonRequest; + + prompt = pBuilder.buildPrompt(Type, token,availableIngredients); + jsonRequest = jsonMapper.writeValueAsString(prompt); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", "Bearer " + API_KEY); + + System.out.println("Sending request to OpenAI"); + + try { + String response = webClient.post() + .uri(OPENAI_URL) + .contentType(MediaType.APPLICATION_JSON) + .headers(h -> h.setAll(headers.toSingleValueMap())) + .body(Mono.just(jsonRequest), String.class) + .retrieve() + .bodyToMono(String.class) + .timeout(Duration.ofSeconds(30)) .block(); return response; diff --git a/backend/src/main/java/fellowship/mealmaestro/services/OpenaiPromptBuilder.java b/backend/src/main/java/fellowship/mealmaestro/services/OpenaiPromptBuilder.java index f8c5f0a8..3cb171b5 100644 --- a/backend/src/main/java/fellowship/mealmaestro/services/OpenaiPromptBuilder.java +++ b/backend/src/main/java/fellowship/mealmaestro/services/OpenaiPromptBuilder.java @@ -105,4 +105,69 @@ public Message buildUserMessage(String type, String token) { return userMessage; } + + public OpenAIChatRequest buildPrompt(String type, String token, String fromIngredients) throws JsonProcessingException { + + OpenAIChatRequest request = new OpenAIChatRequest(); + request.setModel("gpt-3.5-turbo"); + + OpenAIChatRequest.Message systemMessage = buildSystemMessage(); + OpenAIChatRequest.Message userMessage = buildUserMessage(type, token, fromIngredients); + + request.setMessages(List.of(systemMessage, userMessage)); + + return request; + } + + public Message buildUserMessage(String type, String token, String fromIngredients) { + String email = jwtService.extractUserEmail(token); + + UserModel user = userRepository.findByEmail(email).get(); + String pantryFoods = user.getPantry().toString(); + String settings = user.getSettings().toString(); + + double random = rand.nextDouble(); + + OpenAIChatRequest.Message userMessage = new OpenAIChatRequest.Message(); + + System.out.println("1st random: " + random); + + if (pantryFoods.equals("")) { + if (random < 0.3) { + pantryFoods = "I have no food in my pantry"; + } else if (random < 0.6) { + pantryFoods = "There is no food in my pantry"; + } else { + pantryFoods = "I haven't got any food in my pantry"; + } + } else { + pantryFoods = "I have the following foods in my pantry: " + pantryFoods + " And These are my favourite: " + fromIngredients; + } + + random = rand.nextDouble(); + System.out.println("2nd random: " + random); + + if (settings.equals("")) { + if (random < 0.3) { + settings = "You can make whatever unique meal you want."; + } else if (random < 0.6) { + settings = "You can make whatever meal you want."; + } else { + settings = "You can make whatever meal you want, as long as it is " + type + "."; + } + } else { + settings = "Some other useful information about me: " + settings + "."; + } + + random = rand.nextDouble(); + System.out.println("3rd random: " + random); + userMessage.setRole("user"); + if (random < 0.5) { + userMessage.setContent("I want to cook a " + type + " meal. " + pantryFoods + ". " + settings); + } else { + userMessage.setContent("I want to cook a " + type + " meal. " + settings + ". " + pantryFoods); + } + + return userMessage; + } } diff --git a/backend/src/main/java/fellowship/mealmaestro/services/RecommendationService.java b/backend/src/main/java/fellowship/mealmaestro/services/RecommendationService.java new file mode 100644 index 00000000..4305e384 --- /dev/null +++ b/backend/src/main/java/fellowship/mealmaestro/services/RecommendationService.java @@ -0,0 +1,62 @@ +package fellowship.mealmaestro.services; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import fellowship.mealmaestro.models.neo4j.MealModel; + +@Service +public class RecommendationService { + @Autowired + private UserService userService; + @Autowired + private MealDatabaseService mealDatabaseService; + @Autowired + private MealManagementService mealManagementService; + + private final Double MIN_VALUE = -0.2; + + public MealModel getRecommendedMeal(String mealType, String token) throws Exception { + MealModel recMealModel = null; + // get best items that are available in pantry + List bestAvailableIngredients = findCommonItems(userService.getUser(token).getPantry().getNameList(), userService.getUser(token).getView().getPositiveNScores(MIN_VALUE)); + System.out.println("Valid Ingredients" + bestAvailableIngredients); + // protection + if(bestAvailableIngredients == null || bestAvailableIngredients.isEmpty()){ + throw new IllegalArgumentException("No valid ingredients in pantry, Could be empty or no matches"); + } + // use list to find db meal + java.util.Optional recMealFromDatabase = mealDatabaseService.findMealUserLikes(mealType, token, String.join(", ", bestAvailableIngredients)); + // query gpt + if(recMealFromDatabase.isPresent()) + { + return recMealFromDatabase.get(); + } + if(recMealModel == null){ + recMealModel = mealManagementService.generateMealFromIngredients(mealType, token, String.join(", ", bestAvailableIngredients)); + } + return recMealModel; + } + + private static List findCommonItems(List list1, List list2) { + List commonItems = new ArrayList<>(); + + for (String item1 : list1) { + for (String item2 : list2) { + if (item2.toLowerCase().contains(item1.toLowerCase())) { + commonItems.add(item1); + break; + } + if (item1.toLowerCase().contains(item2.toLowerCase())) { + commonItems.add(item2); + break; + } + } + } + + return commonItems; + } +} diff --git a/backend/src/main/java/fellowship/mealmaestro/services/UserService.java b/backend/src/main/java/fellowship/mealmaestro/services/UserService.java index b2f14868..a2c78542 100644 --- a/backend/src/main/java/fellowship/mealmaestro/services/UserService.java +++ b/backend/src/main/java/fellowship/mealmaestro/services/UserService.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Service; +import fellowship.mealmaestro.config.exceptions.UserNotFoundException; import fellowship.mealmaestro.models.UpdateUserRequestModel; import fellowship.mealmaestro.models.neo4j.UserModel; import fellowship.mealmaestro.repositories.neo4j.UserRepository; @@ -28,7 +29,7 @@ public UserModel updateUser(UpdateUserRequestModel user, String token) { String authToken = token.substring(7); String email = jwtService.extractUserEmail(authToken); UserModel userModel = userRepository.findByEmail(email) - .orElseThrow(() -> new RuntimeException("User not found")); + .orElseThrow(() -> new UserNotFoundException("User not found")); userModel.setName(user.getUsername()); return userRepository.save(userModel); @@ -37,6 +38,6 @@ public UserModel updateUser(UpdateUserRequestModel user, String token) { public UserModel getUser(String token) { String authToken = token.substring(7); String email = jwtService.extractUserEmail(authToken); - return userRepository.findByEmail(email).orElseThrow(() -> new RuntimeException("User not found")); + return userRepository.findByEmail(email).orElseThrow(() -> new UserNotFoundException("User not found")); } } diff --git a/backend/src/main/java/fellowship/mealmaestro/services/auth/AuthenticationService.java b/backend/src/main/java/fellowship/mealmaestro/services/auth/AuthenticationService.java index a1c8bea4..2f5c49a9 100644 --- a/backend/src/main/java/fellowship/mealmaestro/services/auth/AuthenticationService.java +++ b/backend/src/main/java/fellowship/mealmaestro/services/auth/AuthenticationService.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import fellowship.mealmaestro.config.exceptions.UserNotFoundException; import fellowship.mealmaestro.models.auth.AuthenticationRequestModel; import fellowship.mealmaestro.models.auth.AuthenticationResponseModel; import fellowship.mealmaestro.models.auth.AuthorityRoleModel; @@ -76,7 +77,7 @@ public AuthenticationResponseModel authenticate(AuthenticationRequestModel reque request.getPassword())); var user = userRepository.findByEmail(request.getEmail()) - .orElseThrow(() -> new RuntimeException("User not found")); + .orElseThrow(() -> new UserNotFoundException("User not found")); var jwt = jwtService.generateToken(user); return new AuthenticationResponseModel(jwt); diff --git a/backend/src/test/java/fellowship/mealmaestro/services/SettingsServiceTest.java b/backend/src/test/java/fellowship/mealmaestro/services/SettingsServiceTest.java deleted file mode 100644 index 0a4a027e..00000000 --- a/backend/src/test/java/fellowship/mealmaestro/services/SettingsServiceTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package fellowship.mealmaestro.services; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.boot.test.context.SpringBootTest; - -import fellowship.mealmaestro.models.neo4j.SettingsModel; -import fellowship.mealmaestro.repositories.neo4j.SettingsRepository; -import fellowship.mealmaestro.services.auth.JwtService; - -import java.util.Arrays; - -@SpringBootTest - -public class SettingsServiceTest { - - @InjectMocks - SettingsService settingsService; - - @Mock - JwtService jwtService; - - @Mock - SettingsRepository settingsRepository; - - @BeforeEach - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetSettings() { - SettingsModel settingsModel = new SettingsModel(); - settingsModel.setGoal("Lose Weight"); - settingsModel.setShoppingInterval("Weekly"); - settingsModel.setFoodPreferences(Arrays.asList("Vegetarian")); - settingsModel.setCalorieAmount(2000); - settingsModel.setBudgetRange("Low"); - settingsModel.setProtein(40); - settingsModel.setCarbs(40); - settingsModel.setFat(20); - settingsModel.setAllergies(Arrays.asList("Peanuts")); - settingsModel.setCookingTime("30 minutes"); - settingsModel.setUserHeight(180); - settingsModel.setUserWeight(70); - settingsModel.setUserBMI(22); - - when(jwtService.extractUserEmail("validToken")).thenReturn("test@example.com"); - when(settingsService.getSettings("test@example.com")).thenReturn(settingsModel); - - SettingsModel result = settingsService.getSettings("validToken"); - - assertEquals(settingsModel, result); - } - - @Test - public void testUpdateSettings() { - SettingsModel settingsModel = new SettingsModel(); - settingsModel.setGoal("Gain Weight"); - settingsModel.setShoppingInterval("Monthly"); - settingsModel.setFoodPreferences(Arrays.asList("Vegan")); - settingsModel.setCalorieAmount(3000); - settingsModel.setBudgetRange("High"); - settingsModel.setProtein(30); - settingsModel.setCarbs(50); - settingsModel.setFat(20); - settingsModel.setAllergies(Arrays.asList("Dairy")); - settingsModel.setCookingTime("45 minutes"); - settingsModel.setUserHeight(175); - settingsModel.setUserWeight(75); - settingsModel.setUserBMI(24); - - when(jwtService.extractUserEmail("validToken")).thenReturn("test@example.com"); - - settingsService.updateSettings(settingsModel, "validToken"); - - verify(settingsService).updateSettings(settingsModel, "test@example.com"); - } -} diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index 7272e81b..b0e7868a 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -2,6 +2,11 @@ import { Component, EnvironmentInjector, inject } from '@angular/core'; import { IonicModule } from '@ionic/angular'; import { CommonModule } from '@angular/common'; +//import { register } from 'swiper'; + +import { register } from 'swiper/element/bundle'; +register(); + @Component({ selector: 'app-root', templateUrl: 'app.component.html', diff --git a/frontend/src/app/components/browse-meals/browse-meals.component.html b/frontend/src/app/components/browse-meals/browse-meals.component.html index 847786b8..40887dd9 100644 --- a/frontend/src/app/components/browse-meals/browse-meals.component.html +++ b/frontend/src/app/components/browse-meals/browse-meals.component.html @@ -91,31 +91,50 @@ - {{mealsData.image}} - + {{mealsData.description}} - {{mealsData.name}} + {{item?.name}} Close - - - - {{mealsData.image}} - + + + -

{{mealsData.ingredients}}

-

{{mealsData.instructions}}

-

{{mealsData.cookingTime}}

+
+ + + + + Save to Recipe Book + +
+

{{ item?.description }}

+

Preparation Time

+

{{ item?.cookingTime }}

+

Ingredients

+
    +
  • {{ ingredient }}
  • +
+

Instructions

+
    +
  1. {{ instruction }}
  2. +
+ + \ No newline at end of file diff --git a/frontend/src/app/components/browse-meals/browse-meals.component.scss b/frontend/src/app/components/browse-meals/browse-meals.component.scss index fd97cd7e..e43fafde 100644 --- a/frontend/src/app/components/browse-meals/browse-meals.component.scss +++ b/frontend/src/app/components/browse-meals/browse-meals.component.scss @@ -1,5 +1,39 @@ +.savebutton { + color: black; + text-transform: capitalize; + font-size: smaller; + margin-right:5px; + margin-left: 5px; +} + +.likebutton { + color: black; + font-size: smaller; + margin-right:5px; + margin-left: 5px; + transition: background-color 0.3 ease; +} + +.savebutton:hover { +background-color: #00c853; +cursor: pointer; +} + +.buttons { + display: flex; + justify-content: space-evenly; +} + ion-avatar { + height: 20vh; width: auto; - height: 15vh; - --border-radius:5%; + --border-radius: 2%; +} + +p { + padding-left: 5vw; } + +ion-content { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} \ No newline at end of file diff --git a/frontend/src/app/components/browse-meals/browse-meals.component.spec.ts b/frontend/src/app/components/browse-meals/browse-meals.component.spec.ts index 7666601e..6869edc0 100644 --- a/frontend/src/app/components/browse-meals/browse-meals.component.spec.ts +++ b/frontend/src/app/components/browse-meals/browse-meals.component.spec.ts @@ -3,6 +3,7 @@ import { IonicModule } from '@ionic/angular'; import { BrowseMealsComponent } from './browse-meals.component'; import { MealI } from '../../models/interfaces'; +import { HttpClientModule } from '@angular/common/http'; describe('BrowseMealsComponent', () => { let component: BrowseMealsComponent; @@ -21,7 +22,7 @@ describe('BrowseMealsComponent', () => { }; TestBed.configureTestingModule({ - imports: [IonicModule.forRoot(), BrowseMealsComponent], + imports: [IonicModule.forRoot(), BrowseMealsComponent, HttpClientModule], }).compileComponents(); fixture = TestBed.createComponent(BrowseMealsComponent); diff --git a/frontend/src/app/components/browse-meals/browse-meals.component.ts b/frontend/src/app/components/browse-meals/browse-meals.component.ts index f6c9e4de..bb10944f 100644 --- a/frontend/src/app/components/browse-meals/browse-meals.component.ts +++ b/frontend/src/app/components/browse-meals/browse-meals.component.ts @@ -2,6 +2,8 @@ import { CommonModule } from '@angular/common'; import { Component, OnInit, Input } from '@angular/core'; import { IonicModule } from '@ionic/angular'; import { MealI } from '../../models/interfaces'; +import { AddRecipeService } from '../../services/recipe-book/add-recipe.service'; +import { AuthenticationService, ErrorHandlerService, LikeDislikeService, LoginService, RecipeBookApiService } from '../../services/services'; @Component({ selector: 'app-browse-meals', @@ -22,13 +24,74 @@ export class BrowseMealsComponent implements OnInit { searchedMeals: MealI[] = []; isModalOpen = false; currentObject: any; + fIns: String[] = []; + fIng: String[] = []; + @Input() items!: MealI[]; - constructor() { } + constructor( + private loginService: LoginService, + private recipeService: RecipeBookApiService, + private auth: AuthenticationService, + private errorHandlerService: ErrorHandlerService, + private likeDislikeService: LikeDislikeService) { } ngOnInit() { // console.log(this.mealsData); + this.item = this.mealsData; + + if (this.item && this.item.instructions) { + this.formatIns(this.item.instructions); + } + + if (this.item && this.item.ingredients) { + this.formatIng(this.item.ingredients); + } + } + + private formatIns(ins: string) { + const insArr: string[] = ins.split(/\d+\.\s+/); + this.fIns = insArr.filter(instruction => instruction.trim() !== ''); + } + + private formatIng(ing: string) { + const ingArr: string[] = ing.split(/,[^()]*?(?![^(]*\))/); + this.fIng = ingArr.map((ingredient) => ingredient.trim()); + } + + async addRecipe(item: MealI) { + this.recipeService.addRecipe(item).subscribe({ + next: (response) => { + if (response.status === 200) { + if (response.body) { + this.getRecipes(); + this.loginService.setRecipeBookRefreshed(false); + this.errorHandlerService.presentSuccessToast( + item.name + ' added to Recipe Book' + ); + } + } + }, + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again.', + err + ); + this.auth.logout(); + } else { + this.errorHandlerService.presentErrorToast( + 'Error adding item to your Recipe Book', + err + ); + } + }, + }); } + notSaved(): boolean { + return !this.items.includes(this.item!); + } + setCurrent(o : any) { this.currentObject = o; } @@ -39,4 +102,58 @@ export class BrowseMealsComponent implements OnInit { this.isModalOpen = isOpen; this.setCurrent(o) } + + async getRecipes() { + this.recipeService.getAllRecipes().subscribe({ + next: (response) => { + if (response.status === 200) { + if (response.body) { + this.items = response.body; + } + } + }, + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } else { + this.errorHandlerService.presentErrorToast( + 'Error loading saved recipes', + err + ); + } + }, + }); + } + + async liked(item: MealI) { + this.likeDislikeService.liked(item).subscribe({ + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } + } + }); + } + + async disliked(item: MealI) { + this.likeDislikeService.disliked(item).subscribe({ + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } + } + }); + } } diff --git a/frontend/src/app/components/daily-meals/daily-meals.component.html b/frontend/src/app/components/daily-meals/daily-meals.component.html index c07f3c94..9498cdda 100644 --- a/frontend/src/app/components/daily-meals/daily-meals.component.html +++ b/frontend/src/app/components/daily-meals/daily-meals.component.html @@ -129,30 +129,47 @@

Cooking Time:

- + + - {{ dayData.lunch?.name }} + {{ item?.name }} - Close + Close - - Lunch Image + + + -

Ingredients:

-

{{ dayData.lunch?.ingredients }}

-

Instructions:

-

{{ dayData.lunch?.instructions }}

-

Cooking time:

-

{{ dayData.lunch?.cookingTime }}

-
-
+
+ + + + + Save to Recipe Book + +
+

{{ item?.description }}

+

Preparation Time

+

{{ item?.cookingTime }}

+

Ingredients:

+
    +
  • {{ ingredient }}
  • +
+

Instructions

+
    +
  1. {{ instruction }}
  2. +
+ +
Cooking time: - {{ dayData.dinner?.name }} - Close + Close - Dinner Image + dayData.dinner.name + -

Ingredients:

-

{{ dayData.dinner?.ingredients }}

-

Instructions:

-

{{ dayData.dinner?.instructions }}

-

Cooking Time:

+
+ + + Save to Recipe Book + +
+

{{ dayData.dinner?.description }}

+

Preparation Time

{{ dayData.dinner?.cookingTime }}

+

Ingredients:

+
    +
  • {{ ingredient }}
  • +
+

Instructions

+
    + +
  1. {{ instruction }}
  2. +
-
{ let component: DailyMealsComponent; @@ -49,7 +50,7 @@ describe('DailyMealsComponent', () => { }; TestBed.configureTestingModule({ - imports: [IonicModule.forRoot(), DailyMealsComponent], + imports: [IonicModule.forRoot(), DailyMealsComponent, HttpClientModule], providers: [ { provide: MealGenerationService, useValue: mockMealGenerationService }, ], diff --git a/frontend/src/app/components/daily-meals/daily-meals.component.ts b/frontend/src/app/components/daily-meals/daily-meals.component.ts index 93ccd77e..0d415263 100644 --- a/frontend/src/app/components/daily-meals/daily-meals.component.ts +++ b/frontend/src/app/components/daily-meals/daily-meals.component.ts @@ -7,12 +7,13 @@ import { QueryList, Renderer2, ElementRef, + ViewChild, } from '@angular/core'; -import { IonItemSliding, IonicModule } from '@ionic/angular'; +import { IonItemSliding, IonicModule, NavController } from '@ionic/angular'; import { Router } from '@angular/router'; import { MealGenerationService } from '../../services/meal-generation/meal-generation.service'; import { DaysMealsI } from '../../models/daysMeals.model'; -import { ErrorHandlerService } from '../../services/services'; +import { AuthenticationService, ErrorHandlerService, LikeDislikeService, LoginService, RecipeBookApiService } from '../../services/services'; import { MealI, RegenerateMealRequestI } from '../../models/interfaces'; import { AddRecipeService } from '../../services/recipe-book/add-recipe.service'; @@ -38,6 +39,11 @@ export class DailyMealsComponent implements OnInit { isBreakfastLoading: boolean = false; isLunchLoading: boolean = false; isDinnerLoading: boolean = false; + item: MealI | undefined; + fIns: String[] = []; + fIng: String[] = []; + @Input() items!: MealI[]; + @ViewChild('saveb') buttonDiv!: ElementRef; constructor( public r: Router, @@ -45,30 +51,95 @@ export class DailyMealsComponent implements OnInit { private errorHandlerService: ErrorHandlerService, private addService: AddRecipeService, private renderer: Renderer2, - private el: ElementRef + private el: ElementRef, + private recipeService: RecipeBookApiService, + private auth: AuthenticationService, + private loginService: LoginService, + private likeDislikeService: LikeDislikeService ) {} setOpen(isOpen: boolean, mealType: string) { - if (mealType === 'breakfast') { - this.isBreakfastModalOpen = isOpen; + if (mealType === 'breakfast') { + this.isModalOpen = isOpen; if (isOpen) { - this.setCurrent(this.dayData?.breakfast); + this.setCurrent(this.dayData?.breakfast); + this.item = this.dayData.breakfast; } - } else if (mealType === 'lunch') { - this.isLunchModalOpen = isOpen; + } else if (mealType === 'lunch') { + this.isModalOpen = isOpen; if (isOpen) { - this.setCurrent(this.dayData?.lunch); + this.setCurrent(this.dayData?.lunch); + this.item = this.dayData.lunch; } } else if (mealType === 'dinner') { - this.isDinnerModalOpen = isOpen; + this.isModalOpen = isOpen; + this.item = this.dayData.dinner; if (isOpen) { this.setCurrent(this.dayData?.dinner); } } + + if (isOpen) { + this.formatIns(this.item!.instructions); + this.formatIng(this.item!.ingredients); + } + } + + async addRecipe(item: MealI) { + this.recipeService.addRecipe(item).subscribe({ + next: (response) => { + if (response.status === 200) { + if (response.body) { + this.getRecipes(); + this.loginService.setRecipeBookRefreshed(false); + this.errorHandlerService.presentSuccessToast( + item.name + ' added to Recipe Book' + ); + } + } + }, + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again.', + err + ); + this.auth.logout(); + } else { + this.errorHandlerService.presentErrorToast( + 'Error adding item to your Recipe Book', + err + ); + } + }, + }); } + private formatIns(ins: string) { + const insArr: string[] = ins.split(/\d+\.\s+/); + this.fIns = insArr.filter(instruction => instruction.trim() !== ''); + } + + private formatIng(ing: string) { + const ingArr: string[] = ing.split(/,[^()]*?(?![^(]*\))/); + this.fIng = ingArr.map((ingredient) => ingredient.trim()); + } + + notSaved(): boolean { + return !this.items.includes(this.item!); + } + ngOnInit() { console.log(this.dayData); + if (this.item && this.item.instructions) { + this.formatIns(this.item.instructions); + } + + if (this.item && this.item.ingredients) { + this.formatIng(this.item.ingredients); + } + + this.getRecipes(); } handleArchive(meal: string) { @@ -146,4 +217,58 @@ export class DailyMealsComponent implements OnInit { return; }); } + + async getRecipes() { + this.recipeService.getAllRecipes().subscribe({ + next: (response) => { + if (response.status === 200) { + if (response.body) { + this.items = response.body; + } + } + }, + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } else { + this.errorHandlerService.presentErrorToast( + 'Error loading saved recipes', + err + ); + } + }, + }); + } + + async liked(item: MealI) { + this.likeDislikeService.liked(item).subscribe({ + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } + } + }); + } + + async disliked(item: MealI) { + this.likeDislikeService.disliked(item).subscribe({ + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } + } + }); + } } diff --git a/frontend/src/app/components/recipe-details/recipe-details.component.html b/frontend/src/app/components/recipe-details/recipe-details.component.html index 70a4ca40..e69de29b 100644 --- a/frontend/src/app/components/recipe-details/recipe-details.component.html +++ b/frontend/src/app/components/recipe-details/recipe-details.component.html @@ -1,27 +0,0 @@ - - - {{ item.name }} - - Close - - - - - - - - -
- - - Save to Recipe Book - -
-

{{ item.description }}

-

Preparation Time

-

{{ item.cookingTime }}

-

Ingredients

-

{{ item.ingredients }}

-

Instructions

-

{{ item.instructions }}

-
\ No newline at end of file diff --git a/frontend/src/app/components/recipe-details/recipe-details.component.scss b/frontend/src/app/components/recipe-details/recipe-details.component.scss index 3364de14..e05b911b 100644 --- a/frontend/src/app/components/recipe-details/recipe-details.component.scss +++ b/frontend/src/app/components/recipe-details/recipe-details.component.scss @@ -2,8 +2,8 @@ color: black; position: fixed; right: 5px; - padding-top: 5px; text-transform: capitalize; + font-size: smaller; } ion-avatar { diff --git a/frontend/src/app/components/recipe-details/recipe-details.component.ts b/frontend/src/app/components/recipe-details/recipe-details.component.ts index 2d436eff..607c68ac 100644 --- a/frontend/src/app/components/recipe-details/recipe-details.component.ts +++ b/frontend/src/app/components/recipe-details/recipe-details.component.ts @@ -1,6 +1,5 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { IonicModule, ModalController } from '@ionic/angular'; -import { RecipeItemI } from '../../models/recipeItem.model'; import { RecipeBookPage } from '../../pages/recipe-book/recipe-book.page'; import { CommonModule } from '@angular/common'; import { AddRecipeService } from '../../services/recipe-book/add-recipe.service'; @@ -17,9 +16,30 @@ export class RecipeDetailsComponent implements OnInit { @Input() item!: MealI; @Input() items!: MealI[]; + fIns: string[] = []; + fIng: string[] = []; + constructor(private modalController: ModalController, private addService: AddRecipeService) { } - ngOnInit() {} + ngOnInit() { + if (this.item && this.item.instructions) { + this.formatIns(this.item.instructions); + } + + if (this.item && this.item.ingredients) { + this.formatIng(this.item.ingredients); + } + } + + private formatIns(ins: string) { + const insArr: string[] = ins.split(/\d+\.\s+/); + this.fIns = insArr.filter(instruction => instruction.trim() !== ''); + } + + private formatIng(ing: string) { + const ingArr: string[] = ing.split(/,[^()]*?(?![^(]*\))/); + this.fIng = ingArr.map((ingredient) => ingredient.trim()); + } closeModal() { this.modalController.dismiss(); diff --git a/frontend/src/app/components/recipe-item/recipe-item.component.html b/frontend/src/app/components/recipe-item/recipe-item.component.html index 8b137891..591d4120 100644 --- a/frontend/src/app/components/recipe-item/recipe-item.component.html +++ b/frontend/src/app/components/recipe-item/recipe-item.component.html @@ -1 +1,37 @@ - + + + + + {{ item?.name }} + + Close + + + + + + + + +
+ + +
+

{{ item?.description }}

+

Preparation Time

+

{{ item?.cookingTime }}

+

Ingredients

+
    +
  • {{ ingredient }}
  • +
+

Instructions

+
    +
  1. {{ instruction }}
  2. +
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/components/recipe-item/recipe-item.component.scss b/frontend/src/app/components/recipe-item/recipe-item.component.scss index e69de29b..8599ac0b 100644 --- a/frontend/src/app/components/recipe-item/recipe-item.component.scss +++ b/frontend/src/app/components/recipe-item/recipe-item.component.scss @@ -0,0 +1,24 @@ +.likebutton { + color: black; + font-size: smaller; + margin-right: 10px; +} + +.buttons { + display: flex; + justify-content: flex-start; +} + +ion-avatar { + height: 20vh; + width: auto; + --border-radius: 2%; +} + +p { + padding-left: 5vw; +} + +ion-content { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} \ No newline at end of file diff --git a/frontend/src/app/components/recipe-item/recipe-item.component.spec.ts b/frontend/src/app/components/recipe-item/recipe-item.component.spec.ts index 4dc016a1..c23fd2b4 100644 --- a/frontend/src/app/components/recipe-item/recipe-item.component.spec.ts +++ b/frontend/src/app/components/recipe-item/recipe-item.component.spec.ts @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { IonicModule } from '@ionic/angular'; import { RecipeItemComponent } from './recipe-item.component'; +import { HttpClientModule } from '@angular/common/http'; describe('RecipeItemComponent', () => { let component: RecipeItemComponent; @@ -9,7 +10,7 @@ describe('RecipeItemComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - imports: [IonicModule.forRoot(), RecipeItemComponent] + imports: [IonicModule.forRoot(), RecipeItemComponent, HttpClientModule] }).compileComponents(); fixture = TestBed.createComponent(RecipeItemComponent); diff --git a/frontend/src/app/components/recipe-item/recipe-item.component.ts b/frontend/src/app/components/recipe-item/recipe-item.component.ts index bd5464b3..88a1114b 100644 --- a/frontend/src/app/components/recipe-item/recipe-item.component.ts +++ b/frontend/src/app/components/recipe-item/recipe-item.component.ts @@ -1,11 +1,8 @@ -import { Component, Input } from '@angular/core'; -import { IonicModule, ModalController } from '@ionic/angular'; -import { RecipeDetailsComponent } from '../recipe-details/recipe-details.component'; - +import { Component } from '@angular/core'; +import { IonicModule } from '@ionic/angular'; import { MealI } from '../../models/meal.model'; import { CommonModule } from '@angular/common'; -import { RecipeItemI } from '../../models/recipeItem.model'; - +import { AuthenticationService, ErrorHandlerService, LikeDislikeService } from '../../services/services'; @Component({ selector: 'app-recipe-item', @@ -18,21 +15,79 @@ import { RecipeItemI } from '../../models/recipeItem.model'; }) export class RecipeItemComponent { items: MealI[] = []; + item!: MealI | undefined; + fIns: string[] = []; + fIng: string[] = []; + modalOpen: Boolean = false; - async openModal(item: any) { - const modal = await this.modalController.create({ - component: RecipeDetailsComponent, - componentProps: { - item: item, - items: this.items - } - }); - await modal.present(); + openModal(item: MealI) { + this.item = item; + this.formatIns(this.item.instructions); + this.formatIng(this.item.ingredients); + this.modalOpen = true; } public passItems(items: MealI[]): void { this.items = items; } - constructor(private modalController: ModalController) { } + constructor(private likeDislikeService: LikeDislikeService, + private errorHandlerService: ErrorHandlerService, + private auth: AuthenticationService) { } + + ngOnInit() { + if (this.item && this.item.instructions) { + this.formatIns(this.item.instructions); + } + + if (this.item && this.item.ingredients) { + this.formatIng(this.item.ingredients); + } + } + + private formatIns(ins: string) { + const insArr: string[] = ins.split(/\d+\.\s+/); + this.fIns = insArr.filter(instruction => instruction.trim() !== ''); + } + + private formatIng(ing: string) { + const ingArr: string[] = ing.split(/,[^()]*?(?![^(]*\))/); + this.fIng = ingArr.map((ingredient) => ingredient.trim()); + } + + closeModal() { + this.modalOpen = false; + } + + notSaved(): boolean { + return !this.items.includes(this.item!); + } + + async liked(item: MealI) { + this.likeDislikeService.liked(item).subscribe({ + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } + } + }); + } + + async disliked(item: MealI) { + this.likeDislikeService.disliked(item).subscribe({ + error: (err) => { + if (err.status === 403) { + this.errorHandlerService.presentErrorToast( + 'Unauthorised access. Please log in again', + err + ); + this.auth.logout(); + } + } + }); + } } diff --git a/frontend/src/app/components/tutorial/tutorial.component.html b/frontend/src/app/components/tutorial/tutorial.component.html new file mode 100644 index 00000000..d8476efb --- /dev/null +++ b/frontend/src/app/components/tutorial/tutorial.component.html @@ -0,0 +1,48 @@ + + + Tutorial + + + + + + + + + + + + +
+ Background Image +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
diff --git a/frontend/src/app/components/tutorial/tutorial.component.scss b/frontend/src/app/components/tutorial/tutorial.component.scss new file mode 100644 index 00000000..5462a448 --- /dev/null +++ b/frontend/src/app/components/tutorial/tutorial.component.scss @@ -0,0 +1,125 @@ + swiper-container { + width: 100%; + height: 100%; + // background-image: url('https://unsplash.com/photos/a-dirt-road-in-the-middle-of-a-grassy-field-9BKSdvsRSuA'); + + // background-color: red; + } + + ion-title { + font-size: 20px; + // font-weight: bold; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); + } + + img { + width: 100%; + height: 100%; + background-size: cover; + background-repeat: no-repeat; + } + + .slide-background { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + } + + + .link-button { + position: fixed; + bottom: 20px; + right: 20px; + font-size: 2.3ch; + color: white; + background: transparent; + font-weight: bold; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); + // background-color: white; + } + .link-but { + position: fixed; + bottom: 20px; + right: 20px; + font-size: 2.5ch; + color: black; + background: transparent; + font-weight: bold; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); + // background-color: white; + } + + + + swiper-slide { + text-align: center; + position: relative; + // font-size: 18px; + // background-color: red; + display: flex; + justify-content: center; + align-items: center; + } + swiper-button-next { color: red; } + + .closeButton { + color: white; + // box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); + // text-shadow: 2px 2px black; + } + + .bar { + // text-shadow: 2px 2px black; + color:#53BB63; + color: white; + --background: #53BB63; + //font-size: 12px; + // --background: white; + } + + .swiper-pagination-bullet-active { + background-color: #000 !important; +} + + // ion-icon { + // text-shadow: 10px 10px 10px blue; + // } + + .swiper-container .swiper-button-next, + .swiper-container .swiper-button-prev { + background-color: #53BB63; + color: #53BB63; + } + + + video { + width: 100%; + height: 100%; + object-fit: fill; + } + + /* Initial tooltip style, hidden by default */ +.tooltip { + display: none; + position: absolute; + background-color: #333; + color: #fff; + padding: 5px 10px; + border-radius: 5px; + font-size: 14px; + z-index: 9999; +} + +/* Tooltip arrow */ +.tooltip::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: #333 transparent transparent transparent; +} diff --git a/frontend/src/app/components/tutorial/tutorial.component.spec.ts b/frontend/src/app/components/tutorial/tutorial.component.spec.ts new file mode 100644 index 00000000..91809af4 --- /dev/null +++ b/frontend/src/app/components/tutorial/tutorial.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { TutorialComponent } from './tutorial.component'; + +describe('TutorialComponent', () => { + let component: TutorialComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [IonicModule.forRoot()] + }).compileComponents(); + + fixture = TestBed.createComponent(TutorialComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/components/tutorial/tutorial.component.ts b/frontend/src/app/components/tutorial/tutorial.component.ts new file mode 100644 index 00000000..5f3114d5 --- /dev/null +++ b/frontend/src/app/components/tutorial/tutorial.component.ts @@ -0,0 +1,88 @@ +import { Component, ViewChild, ElementRef,OnInit, AfterViewInit , CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ModalController } from '@ionic/angular'; +import {IonicModule } from '@ionic/angular'; +import { AuthenticationService, ErrorHandlerService } from '../../services/services'; +import { CommonModule } from '@angular/common'; +import Swiper from 'swiper'; + + +@Component({ + + selector: 'app-tutorial', + templateUrl: './tutorial.component.html', + styleUrls: ['./tutorial.component.scss'], + standalone:true, + imports: [CommonModule, IonicModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA], +}) +export class TutorialComponent implements OnInit, AfterViewInit { + + private swiper: Swiper = {} as Swiper; + @ViewChild('swiper') swiperElement!: ElementRef; + @ViewChild('videoPlayer') videoPlayer!: ElementRef; + + constructor(private modalController: ModalController, private errorHandlerService: ErrorHandlerService) { } + + ngOnInit() {} + + ngAfterViewInit() { + //console.log('called'); + this.swiper = new Swiper('.swiper-container', { + // Swiper configuration options + pagination: { + el: '.swiper-pagination', + type: 'progressbar', + }, + navigation: { + nextEl: '.swiper-button-next', + prevEl: '.swiper-button-prev', + }, + on: { + slideChange: () => { + console.log('slides started'); + this.onSlideChange(); + }, + slideChangeTransitionStart: () => { + console.log('transition started'); + this.onSlideChangeTransitionStart(); + }, + }, + }); + // this.swiper.on('slideChange', () => { + // console.log("IN FUNCTION") + // this.onSlideChange(); + // }) + // console.log('done'); + } + + onSlideChange() { + console.log('slide changed'); + //if (this.swiper.isEnd) { + const video: HTMLVideoElement = this.videoPlayer.nativeElement; + const activeSlide = this.swiper.slides[this.swiper.activeIndex]; + if (activeSlide.classList.contains('swip')) { + // If the active slide contains the video, play it + video.play(); + } else { + // If the active slide doesn't contain the video, pause it + video.pause(); + } + //video.pause(); + // } + } + + onSlideChangeTransitionStart() { + console.log('slide started'); + const video: HTMLVideoElement = this.videoPlayer.nativeElement; + video.currentTime = 0; + } + + + onSwiper(swiper: Swiper) { + this.swiper = swiper; + } + + closeModal() { + this.modalController.dismiss(); + } +} diff --git a/frontend/src/app/models/settings.model.ts b/frontend/src/app/models/settings.model.ts index a5988a48..036544d7 100644 --- a/frontend/src/app/models/settings.model.ts +++ b/frontend/src/app/models/settings.model.ts @@ -2,7 +2,7 @@ export interface SettingsI { goal: string; shoppingInterval: string; foodPreferences: string[]; - calorieAmount: number; + calorieAmount: number | string; budgetRange: string; protein: number; @@ -13,7 +13,7 @@ export interface SettingsI { cookingTime: string; userHeight: number; //consider moving to account userWeight: number; //consider moving to account - userBMI: number; + userBMI: number | string; bmiset: boolean; cookingTimeSet: boolean; diff --git a/frontend/src/app/pages/acc-profile/acc-profile.page.html b/frontend/src/app/pages/acc-profile/acc-profile.page.html index 6f9e50de..72cd448f 100644 --- a/frontend/src/app/pages/acc-profile/acc-profile.page.html +++ b/frontend/src/app/pages/acc-profile/acc-profile.page.html @@ -4,6 +4,15 @@ + + + + + @@ -25,9 +34,9 @@ Logout - Delete Account + > --> @@ -62,6 +63,7 @@ diff --git a/frontend/src/app/pages/browse/browse.page.spec.ts b/frontend/src/app/pages/browse/browse.page.spec.ts index 2e6bcf8a..127f71c2 100644 --- a/frontend/src/app/pages/browse/browse.page.spec.ts +++ b/frontend/src/app/pages/browse/browse.page.spec.ts @@ -8,6 +8,7 @@ import { AuthenticationService, MealGenerationService, } from '../../services/services'; +import { HttpClientModule } from '@angular/common/http'; describe('BrowsePage', () => { let component: BrowsePage; @@ -19,7 +20,7 @@ describe('BrowsePage', () => { mockAuthService = jasmine.createSpyObj('AuthenticationService', ['logout']); await TestBed.configureTestingModule({ - imports: [BrowsePage, IonicModule, RecipeItemComponent], + imports: [BrowsePage, IonicModule, RecipeItemComponent, HttpClientModule], providers: [ { provide: MealGenerationService, useValue: mockMealGenerationService }, { provide: AuthenticationService, useValue: mockAuthService }, diff --git a/frontend/src/app/pages/browse/browse.page.ts b/frontend/src/app/pages/browse/browse.page.ts index 8c1b3fb0..d9e8394a 100644 --- a/frontend/src/app/pages/browse/browse.page.ts +++ b/frontend/src/app/pages/browse/browse.page.ts @@ -7,6 +7,7 @@ import { MealGenerationService } from '../../services/meal-generation/meal-gener import { AuthenticationService, ErrorHandlerService, + RecipeBookApiService, } from '../../services/services'; import { MealI } from '../../models/interfaces'; @@ -25,12 +26,14 @@ export class BrowsePage implements OnInit { Loading: boolean = false; searchQuery: string = ''; searchResults: any; + recipeItems: MealI[] = []; constructor( public r: Router, private mealGenerationservice: MealGenerationService, private errorHandlerService: ErrorHandlerService, - private auth: AuthenticationService + private auth: AuthenticationService, + private recipeService: RecipeBookApiService ) { this.searchQuery = ''; } diff --git a/frontend/src/app/pages/home/home.page.html b/frontend/src/app/pages/home/home.page.html index 7edbb528..7455e836 100644 --- a/frontend/src/app/pages/home/home.page.html +++ b/frontend/src/app/pages/home/home.page.html @@ -23,7 +23,7 @@ - + diff --git a/frontend/src/app/pages/home/home.page.spec.ts b/frontend/src/app/pages/home/home.page.spec.ts index 058b922c..a56d0d3b 100644 --- a/frontend/src/app/pages/home/home.page.spec.ts +++ b/frontend/src/app/pages/home/home.page.spec.ts @@ -6,6 +6,7 @@ import { AuthenticationService, MealGenerationService, } from '../../services/services'; +import { HttpClientModule } from '@angular/common/http'; describe('HomePage', () => { let component: HomePage; @@ -18,7 +19,7 @@ describe('HomePage', () => { mockAuthService = jasmine.createSpyObj('AuthenticationService', ['logout']); await TestBed.configureTestingModule({ - imports: [HomePage, IonicModule, DailyMealsComponent], + imports: [HomePage, IonicModule, DailyMealsComponent, HttpClientModule], providers: [ { provide: MealGenerationService, useValue: mockMealGenerationService }, { provide: AuthenticationService, useValue: mockAuthService }, diff --git a/frontend/src/app/pages/home/home.page.ts b/frontend/src/app/pages/home/home.page.ts index 4d8703f0..7c634ea2 100644 --- a/frontend/src/app/pages/home/home.page.ts +++ b/frontend/src/app/pages/home/home.page.ts @@ -15,8 +15,10 @@ import { ErrorHandlerService, LoginService, MealGenerationService, + RecipeBookApiService, } from '../../services/services'; import { CommonModule } from '@angular/common'; +import { MealI } from '../../models/interfaces'; @Component({ selector: 'app-home', @@ -32,6 +34,8 @@ export class HomePage implements OnInit, ViewWillEnter { isLoading: boolean = true; showLoading: boolean = true; + recipeItems: MealI[] = []; + constructor( public r: Router, private renderer: Renderer2, @@ -39,7 +43,8 @@ export class HomePage implements OnInit, ViewWillEnter { private mealGenerationservice: MealGenerationService, private errorHandlerService: ErrorHandlerService, private loginService: LoginService, - private auth: AuthenticationService + private auth: AuthenticationService, + private recipeService: RecipeBookApiService ) {} async ngOnInit() { @@ -64,7 +69,6 @@ export class HomePage implements OnInit, ViewWillEnter { ); }); - // await this.getMeals(); } async ionViewWillEnter() { @@ -106,6 +110,7 @@ export class HomePage implements OnInit, ViewWillEnter { await new Promise((resolve, reject) => { this.mealGenerationservice.getDailyMeals(date).subscribe({ next: (data) => { + console.log('Received data:', data); if (data.body) { let mealsForDay: DaysMealsI = { breakfast: undefined, diff --git a/frontend/src/app/pages/login/login.page.html b/frontend/src/app/pages/login/login.page.html index f7d6d83a..5cde8b7e 100644 --- a/frontend/src/app/pages/login/login.page.html +++ b/frontend/src/app/pages/login/login.page.html @@ -2,54 +2,65 @@
- +
-
+
- - - -
- Please enter a valid email. -
- - -
- Please enter a password. -
-
- - - Login + + +
+ Please enter a valid email. +
+ + +
+ Please enter a password. +
- -
+ + + + Login + + +
- Forget Password? + - + -
- \ No newline at end of file + diff --git a/frontend/src/app/pages/pantry/pantry.page.spec.ts b/frontend/src/app/pages/pantry/pantry.page.spec.ts index 474e5a82..f24fb3da 100644 --- a/frontend/src/app/pages/pantry/pantry.page.spec.ts +++ b/frontend/src/app/pages/pantry/pantry.page.spec.ts @@ -6,6 +6,7 @@ import { of } from 'rxjs'; import { FoodItemI } from '../../models/interfaces'; import { AuthenticationService, + BarcodeApiService, PantryApiService, ShoppingListApiService, } from '../../services/services'; @@ -17,6 +18,7 @@ describe('PantryPage', () => { let mockPantryService: jasmine.SpyObj; let mockShoppingListService: jasmine.SpyObj; let mockAuthService: jasmine.SpyObj; + let mockBarcodeService: jasmine.SpyObj; let mockItems: FoodItemI[]; beforeEach(async () => { @@ -31,11 +33,15 @@ describe('PantryPage', () => { 'deleteShoppingListItem', ]); mockAuthService = jasmine.createSpyObj('AuthenticationService', ['logout']); + mockBarcodeService = jasmine.createSpyObj('BarcodeApiService', [ + 'findProduct', + ]); mockItems = [ { name: 'test', quantity: 1, unit: 'pcs', + price: 2, }, { name: 'test2', @@ -53,6 +59,10 @@ describe('PantryPage', () => { body: mockItems[0], status: 200, }); + const barcodeResponse = new HttpResponse({ + body: mockItems[0], + status: 200, + }); mockPantryService.getPantryItems.and.returnValue(of(itemsResponse)); mockPantryService.addToPantry.and.returnValue(of(itemResponse)); @@ -64,6 +74,7 @@ describe('PantryPage', () => { mockShoppingListService.deleteShoppingListItem.and.returnValue( of(emptyResponse) ); + mockBarcodeService.findProduct.and.returnValue(of(barcodeResponse)); await TestBed.configureTestingModule({ imports: [IonicModule, PantryPage], @@ -71,6 +82,7 @@ describe('PantryPage', () => { { provide: PantryApiService, useValue: mockPantryService }, { provide: ShoppingListApiService, useValue: mockShoppingListService }, { provide: AuthenticationService, useValue: mockAuthService }, + { provide: BarcodeApiService, useValue: mockBarcodeService }, ], }).compileComponents(); @@ -83,8 +95,8 @@ describe('PantryPage', () => { expect(component).toBeTruthy(); }); - it('#ngOnInit should call getPantryItems and getShoppingListItems', () => { - component.ngOnInit(); + it('#viewWillEnter should call getPantryItems and getShoppingListItems', () => { + component.ionViewWillEnter(); expect(mockPantryService.getPantryItems).toHaveBeenCalled(); expect(mockShoppingListService.getShoppingListItems).toHaveBeenCalled(); diff --git a/frontend/src/app/pages/pantry/pantry.page.ts b/frontend/src/app/pages/pantry/pantry.page.ts index 7927003b..475cc2ac 100644 --- a/frontend/src/app/pages/pantry/pantry.page.ts +++ b/frontend/src/app/pages/pantry/pantry.page.ts @@ -70,12 +70,14 @@ export class PantryPage implements OnInit, ViewWillEnter { private alertController: AlertController ) {} + async ngOnInit() { BarcodeScanner.isSupported().then((result) => { this.isBarcodeSupported = result.supported; }); } + async ionViewWillEnter() { if (!this.loginService.isPantryRefreshed()) { this.fetchItems(); @@ -303,7 +305,13 @@ export class PantryPage implements OnInit, ViewWillEnter { calculateTotalPrice() { this.totalShoppingPrice = 0; this.shoppingItems.forEach((item) => { - if (item.price) { + if ( + item.price && + item.price !== undefined && + item.price !== null && + item.price !== 0 && + item.price !== -1 + ) { this.totalShoppingPrice += item.price; } }); diff --git a/frontend/src/app/pages/profile/profile.page.html b/frontend/src/app/pages/profile/profile.page.html index ee24f983..50dfc9c3 100644 --- a/frontend/src/app/pages/profile/profile.page.html +++ b/frontend/src/app/pages/profile/profile.page.html @@ -5,12 +5,15 @@ - - - - - {{this.user.username}}'s Profile + + + + + + {{ this.user.username }}'s Profile + @@ -37,7 +40,7 @@
Shopping Interval
-
{{ settings.shoppingInterval }}
+
{{ getDisplayShoppingInterval() }}
@@ -52,7 +55,10 @@ Cancel - Confirm @@ -114,7 +120,8 @@ Every {{ shoppingIntervalOtherValue }} day(s)Every {{ getDisplayOtherShoppingInterval() }} + day(s) @@ -182,6 +189,7 @@ ConfirmCancel - Confirm @@ -394,22 +405,6 @@ >High Budget - - Custom Amount - - - - @@ -624,7 +619,10 @@ Cancel - Confirm @@ -717,10 +715,7 @@ Cancel - Confirm @@ -743,6 +738,7 @@ { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - //removed ProfilePage from declarations imports: [IonicModule.forRoot(), HttpClientTestingModule, RouterTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] // added this line + schemas: [CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); diff --git a/frontend/src/app/pages/profile/profile.page.ts b/frontend/src/app/pages/profile/profile.page.ts index 7097eea9..dcca8854 100644 --- a/frontend/src/app/pages/profile/profile.page.ts +++ b/frontend/src/app/pages/profile/profile.page.ts @@ -1,5 +1,10 @@ import { Component, OnInit } from '@angular/core'; -import { IonicModule, PickerController, ViewWillEnter } from '@ionic/angular'; +import { + IonicModule, + PickerController, + ViewWillEnter, + ToastController, +} from '@ionic/angular'; import { FormsModule } from '@angular/forms'; import { SettingsI } from '../../models/settings.model'; @@ -28,11 +33,9 @@ export class ProfilePage implements OnInit, ViewWillEnter { private settingsApiService: SettingsApiService, private auth: AuthenticationService, private loginService: LoginService, - private errorHandlerService: ErrorHandlerService - ) { - this.selectedPriceRange = ''; - } - + private errorHandlerService: ErrorHandlerService, + private toastController: ToastController + ) {} // User data user: UserI = { username: '', @@ -65,16 +68,14 @@ export class ProfilePage implements OnInit, ViewWillEnter { shoppingIntervalSet: false, }; - // Variables for displaying displaying_Macroratio: string | undefined; - shoppingIntervalOtherValue: number | undefined | any; + shoppingIntervalOtherValue: number | undefined | any = 7; shoppingInterval: string | any; displayAllergies: string[] | string = ''; displayPreferences: string[] | string = ''; selectedPreferences: string | any; - selectedPriceRange: string; + selectedPriceRange: string | any; - // Check if possible to change preferences = { vegetarian: false, vegan: false, @@ -89,7 +90,6 @@ export class ProfilePage implements OnInit, ViewWillEnter { eggs: false, }; - // Modal controllers isPreferencesModalOpen: boolean = false; isCalorieModalOpen: boolean = false; isBudgetModalOpen: boolean = false; @@ -99,7 +99,7 @@ export class ProfilePage implements OnInit, ViewWillEnter { isBMIModalOpen: boolean = false; isShoppingModalOpen: boolean = false; - // + //toggle logic shoppingintervalToggle: boolean = false; preferenceToggle: boolean = false; calorieToggle: boolean = false; @@ -109,6 +109,36 @@ export class ProfilePage implements OnInit, ViewWillEnter { cookingToggle: boolean = false; BMIToggle: boolean = false; + + //reset logic for cancel button + initialshoppinginterval: string | any; + initialpreference: string | any; + initialpreferenceVegetarian: string | any; + initialpreferenceVegan: string | any; + initialpreferenceGlutenIntolerant: string | any; + initialpreferenceLactoseIntolerant: string | any; + initialcalorie: number | any; + initialbudget: string | any; + initialprotein: number | any; + initialcarbs: number | any; + initialfat: number | any; + initialallergies: string | any; + initialallergiesSeafood: string | any; + initialallergiesNuts: string | any; + initialallergiesEggs: string | any; + initialallergiesSoy: string | any; + + initialcooking: string | any; + initialBMI: number | any; + initialshoppingintervalToggle: boolean | any; + initialpreferenceToggle: boolean | any; + initialcalorieToggle: boolean | any; + initialbudgetToggle: boolean | any; + initialmacroToggle: boolean | any; + initialallergiesToggle: boolean | any; + initialcookingToggle: boolean | any; + initialBMIToggle: boolean | any; + ngOnInit() {} ionViewWillEnter(): void { @@ -148,37 +178,101 @@ export class ProfilePage implements OnInit, ViewWillEnter { next: (response) => { if (response.status === 200) { if (response.body) { + console.log('loaduser'); + console.log(response.body); this.settings.goal = response.body.goal; - this.settings.shoppingInterval = response.body.shoppingInterval; - this.settings.foodPreferences = response.body.foodPreferences; + if (response.body.shoppingInterval != '') { + this.settings.shoppingIntervalSet = true; + } - if (response.body.calorieAmount == null) { - this.settings.calorieAmount = 0; - } else this.settings.calorieAmount = response.body.calorieAmount; + if ( + response.body.shoppingInterval === 'weekly' || + response.body.shoppingInterval === 'biweekly' || + response.body.shoppingInterval === 'monthly' + ) { + this.settings.shoppingInterval = response.body.shoppingInterval; + this.shoppingInterval = response.body.shoppingInterval; + } else if (response.body.shoppingInterval.includes('days')) { + this.settings.shoppingInterval = 'other'; + this.shoppingIntervalOtherValue = response.body.shoppingInterval; + } else { + this.settings.shoppingIntervalSet = false; + this.settings.shoppingInterval = ''; + this.shoppingInterval = ''; + } - this.settings.budgetRange = response.body.budgetRange; + this.settings.foodPreferences = response.body.foodPreferences; + if (response.body.calorieAmount == 0) { + this.settings.calorieAmount = ''; + } else { + this.settings.calorieAmount = response.body.calorieAmount; + } + + console.log('budget'); + console.log(response.body.budgetRange); + if (response.body.budgetRange.includes('R')) { + this.settings.budgetRange = response.body.budgetRange; + this.selectedPriceRange = 'custom'; + } else { + this.settings.budgetRange = response.body.budgetRange; + this.selectedPriceRange = response.body.budgetRange; + } this.settings.allergies = response.body.allergies; this.settings.cookingTime = response.body.cookingTime; this.settings.userHeight = response.body.userHeight; this.settings.userWeight = response.body.userWeight; - this.settings.userBMI = response.body.userBMI; + if (response.body.userBMI == 0) { + this.settings.userBMI = ''; + } else this.settings.userBMI = response.body.userBMI; this.settings.bmiset = response.body.bmiset; this.settings.cookingTimeSet = response.body.cookingTimeSet; this.settings.allergiesSet = response.body.allergiesSet; - this.settings.macroSet = response.body.macroSet; + if ( + response.body.protein > 0 && + response.body.carbs > 0 && + response.body.fat > 0 && + response.body.macroSet === true + ) { + this.settings.macroSet = true; + } else if ( + response.body.protein === 0 || + response.body.carbs === 0 || + response.body.fat === 0 || + response.body.macroSet === false + ) { + this.settings.macroSet = false; + } this.settings.budgetSet = response.body.budgetSet; this.settings.calorieSet = response.body.calorieSet; - this.settings.foodPreferenceSet = response.body.foodPreferenceSet; this.settings.shoppingIntervalSet = response.body.shoppingIntervalSet; this.settings.fat = response.body.fat; this.settings.carbs = response.body.carbs; this.settings.protein = response.body.protein; - this.displayPreferences = this.settings.foodPreferences; this.displayAllergies = this.settings.allergies; + + this.shoppingintervalToggle = this.settings.shoppingIntervalSet; + this.calorieToggle = this.settings.calorieSet; + this.budgetToggle = this.settings.budgetSet; + + this.allergiesToggle = this.settings.allergiesSet; + this.cookingToggle = this.settings.cookingTimeSet; + this.BMIToggle = this.settings.bmiset; + this.shoppingInterval = this.settings.shoppingInterval; + this.displaying_Macroratio = this.getDisplayMacroratio(); this.updateDisplayData(); + + this.setInitialAllergies(); + this.setInitialBMI(); + this.setInitialBudget(); + this.setInitialCalorie(); + this.setInitialCooking(); + this.setIntialPreference(); + this.setInitialMacro(); + this.setInitialShopping(); + this.setInitialBMI(); } } }, @@ -204,7 +298,19 @@ export class ProfilePage implements OnInit, ViewWillEnter { } private updateSettingsOnServer() { + console.log('update'); + //if check to ensure only 1 "days" is in the string + if ( + this.settings.shoppingInterval.includes('days') && + this.settings.shoppingInterval.split('days').length - 1 > 1 + ) { + this.settings.shoppingInterval = this.settings.shoppingInterval + .replace('days', '') + .trim(); + } + console.log(this.settings); + this.settingsApiService.updateSettings(this.settings).subscribe({ next: (response) => { if (response.status === 200) { @@ -229,7 +335,6 @@ export class ProfilePage implements OnInit, ViewWillEnter { }, }); } - // Function to navigate to account-profile page navToProfile() { this.router.navigate(['acc-profile']); @@ -243,32 +348,39 @@ export class ProfilePage implements OnInit, ViewWillEnter { setOpenPreferences(isOpen: boolean) { this.isPreferencesModalOpen = isOpen; + this.resetPreference(); } setOpenPreferencesSave(isOpen: boolean) { + console.log('Saving Preferences'); if (this.settings.foodPreferenceSet === true) { + this.getSelectedPreferences(); // This will update this.settings.foodPreferences if ( - this.preferences.vegetarian || - this.preferences.vegan || - this.preferences.glutenIntolerant || - this.preferences.lactoseIntolerant + !this.preferences.vegetarian && + !this.preferences.vegan && + !this.preferences.glutenIntolerant && + !this.preferences.lactoseIntolerant ) { - if (!isOpen) { - this.updateDisplayData(); // Update the display data when the modal is closed - } - this.isPreferencesModalOpen = isOpen; + this.presentToast( + 'Please select at least one food preference. If you have no food preferences, please uncheck the food preferences toggle.' + ); + return; } - } else if (this.settings.foodPreferenceSet === false) { + if (!isOpen) { + this.updateDisplayData(); // Update the display data when the modal is closed + } + this.isPreferencesModalOpen = isOpen; + } else { this.settings.foodPreferences = []; this.displayPreferences = ''; this.isPreferencesModalOpen = isOpen; } + this.setIntialPreference(); this.updateSettingsOnServer(); } preference_Toggle() { this.settings.foodPreferenceSet = !this.settings.foodPreferenceSet; - this.updateSettingsOnServer(); } getSelectedPreferences(): string { @@ -320,6 +432,7 @@ export class ProfilePage implements OnInit, ViewWillEnter { setOpenCalorie(isOpen: boolean) { this.isCalorieModalOpen = isOpen; + this.resetCalorie(); } setOpenCalorieSave(isOpen: boolean) { @@ -331,15 +444,15 @@ export class ProfilePage implements OnInit, ViewWillEnter { this.isCalorieModalOpen = isOpen; } } else if (this.settings.calorieSet === false) { - this.settings.calorieAmount = 0; + this.settings.calorieAmount = ''; this.isCalorieModalOpen = isOpen; } + this.setInitialCalorie(); this.updateSettingsOnServer(); } calorieAmount_Toggle() { this.settings.calorieSet = !this.settings.calorieSet; - this.updateSettingsOnServer(); } showSelectedCalorieAmount(event: any) { @@ -348,22 +461,68 @@ export class ProfilePage implements OnInit, ViewWillEnter { setOpenBudget(isOpen: boolean) { this.isBudgetModalOpen = isOpen; + this.resetBudget(); } setOpenBudgetSave(isOpen: boolean) { + console.log('setOpenBudgetSave called with:', isOpen); // Debug 1 + if (this.settings.budgetSet === true) { - this.settings.budgetRange = this.selectedPriceRange; - this.isBudgetModalOpen = isOpen; - } else if (this.settings.budgetSet === false) { + console.log('Budget is set.'); // Debug 2 + + if (this.selectedPriceRange === 'custom') { + console.log('Custom range selected.'); // Debug 3 + + if ( + this.settings.budgetRange !== null && + this.settings.budgetRange !== undefined + ) { + console.log('Budget range is neither null nor undefined.'); // Debug 4 + + const budgetString = this.settings.budgetRange.toString(); + const rCount = (budgetString.match(/R/g) || []).length; + + const isValid = /^[R]?[0-9\s]*$/.test(budgetString); + + if (!isValid) { + this.settings.budgetRange = budgetString.replace(/[^0-9R\s]/g, ''); + } + + if (rCount > 1) { + this.settings.budgetRange = budgetString.replace(/R/g, '').trim(); + this.settings.budgetRange = 'R ' + this.settings.budgetRange; + } else if (rCount === 0) { + this.settings.budgetRange = 'R ' + budgetString; + } + } + } else { + this.settings.budgetRange = this.selectedPriceRange; + } + + this.isBudgetModalOpen = false; + console.log('Attempting to close the modal.'); // Debug 5 + } else { this.settings.budgetRange = ''; - this.isBudgetModalOpen = isOpen; + this.isBudgetModalOpen = false; } + + this.setInitialBudget(); this.updateSettingsOnServer(); + console.log('Function completed.'); // Debug 6 + } + + validateBudgetInput(event: Event) { + const input = event.target as HTMLInputElement; + const value = input.value; + + input.value = value.replace(/[^0-9.]/g, ''); } budgetRange_Toggle() { this.settings.budgetSet = !this.settings.budgetSet; - this.updateSettingsOnServer(); + if (!this.settings.budgetSet && this.selectedPriceRange === 'custom') { + this.settings.budgetRange = ''; + } } async openPicker() { @@ -415,7 +574,6 @@ export class ProfilePage implements OnInit, ViewWillEnter { this.settings.protein = value['protein'].value; this.settings.carbs = value['carbs'].value; this.settings.fat = value['fat'].value; - this.updateSettingsOnServer(); }, }, ], @@ -423,16 +581,16 @@ export class ProfilePage implements OnInit, ViewWillEnter { await picker.present(); } - setOpenMacro(isOpen: boolean) { this.isMacroModalOpen = isOpen; + this.resetMacro(); } - setOpenMacroSave(isOpen: boolean) { if (this.settings.macroSet === true) { if (!isOpen) { - this.displaying_Macroratio = this.getDisplayMacroratio(); // Update the display data when the modal is closed + this.displaying_Macroratio = this.getDisplayMacroratio(); } + this.isMacroModalOpen = isOpen; } else if (this.settings.macroSet === false) { this.settings.protein = 0; @@ -441,44 +599,45 @@ export class ProfilePage implements OnInit, ViewWillEnter { this.displaying_Macroratio = ''; this.isMacroModalOpen = isOpen; } + this.setInitialMacro(); this.updateSettingsOnServer(); } - macro_Toggle() { this.settings.macroSet = !this.settings.macroSet; - this.updateSettingsOnServer(); } - setOpenAllergies(isOpen: boolean) { this.isAllergiesModalOpen = isOpen; + this.resetAllergies(); } - setOpenAllergiesSave(isOpen: boolean) { if (this.settings.allergiesSet === true) { if ( - this.allergens.seafood || - this.allergens.nuts || - this.allergens.eggs || - this.allergens.soy + !this.allergens.seafood && + !this.allergens.nuts && + !this.allergens.eggs && + !this.allergens.soy ) { - if (!isOpen) { - this.displayAllergies = this.getSelectedAllergens(); // Update the display data when the modal is closed - } - this.isAllergiesModalOpen = isOpen; + this.presentToast( + 'Please select at least one allergen. if you have no allergies, please uncheck the allergies toggle.' + ); + return; + } + if (!isOpen) { + this.displayAllergies = this.getSelectedAllergens(); // Update the display data when the modal is closed } - } else if (this.settings.allergiesSet === false) { + this.isAllergiesModalOpen = isOpen; + } else { this.settings.allergies = []; this.displayAllergies = ''; this.isAllergiesModalOpen = isOpen; } + this.setInitialAllergies(); this.updateSettingsOnServer(); } allergies_Toggle() { this.settings.allergiesSet = !this.settings.allergiesSet; - this.updateSettingsOnServer(); } - getSelectedAllergens(): string { const selectedAllergens = []; if (this.settings.allergies == null) { @@ -506,7 +665,6 @@ export class ProfilePage implements OnInit, ViewWillEnter { selectedAllergens.push('Soy'); this.settings.allergies.push('Soy'); } - if (selectedAllergens.length === 1) { return selectedAllergens[0]; } else if (selectedAllergens.length > 1) { @@ -516,11 +674,10 @@ export class ProfilePage implements OnInit, ViewWillEnter { } } } - setOpenCooking(isOpen: boolean) { + this.resetCooking(); this.isCookingModalOpen = isOpen; } - setOpenCookingSave(isOpen: boolean) { if (this.settings.cookingTimeSet === true) { this.isCookingModalOpen = isOpen; @@ -528,45 +685,69 @@ export class ProfilePage implements OnInit, ViewWillEnter { this.settings.cookingTime = ''; this.isCookingModalOpen = isOpen; } + this.setInitialCooking(); this.updateSettingsOnServer(); } - cookingtime_Toggle() { this.settings.cookingTimeSet = !this.settings.cookingTimeSet; - this.updateSettingsOnServer(); } - setOpenBMI(isOpen: boolean) { + this.resetBMI(); this.isBMIModalOpen = isOpen; } - setOpenBMISave(isOpen: boolean) { - if (this.settings.userHeight && this.settings.userWeight) { - this.updateDisplayData(); // Update the display data when the modal is closed - this.isBMIModalOpen = isOpen; + if ( + this.settings.bmiset === true && + this.settings.userHeight > 0 && + this.settings.userWeight > 0 + ) { + if (this.settings.userHeight > 0 && this.settings.userWeight > 0) { + this.calculateBMI(); + this.updateDisplayData(); + this.updateSettingsOnServer(); + this.isBMIModalOpen = isOpen; + } } - if (this.settings.bmiset === false) { - this.settings.userBMI = 0; + this.settings.userHeight = 0; + this.settings.userWeight = 0; + this.settings.userBMI = ''; this.isBMIModalOpen = isOpen; } + this.setInitialBMI(); this.updateSettingsOnServer(); } BMI_Toggle() { this.settings.bmiset = !this.settings.bmiset; - this.updateSettingsOnServer(); } setOpenShopping(isOpen: boolean) { - this.isShoppingModalOpen = isOpen; + if (isOpen === false) { + console.log('resetClose'); + console.log(this.settings.shoppingInterval); + this.resetShopping(); + console.log(this.settings.shoppingInterval); + this.isShoppingModalOpen = isOpen; + } else if (isOpen === true) { + console.log('resetOpen'); + if (this.settings.shoppingInterval.includes('days')) { + this.shoppingInterval = 'other'; + this.shoppingIntervalOtherValue = this.settings.shoppingInterval + .replace('days', '') + .trim(); + } + console.log(this.settings.shoppingInterval); + + this.isShoppingModalOpen = isOpen; + } } setOpenShoppingSave(isOpen: boolean) { if (this.settings.shoppingIntervalSet === true) { if (this.shoppingInterval === 'other') { this.settings.shoppingInterval = - this.shoppingIntervalOtherValue.toString(); + this.shoppingIntervalOtherValue.toString() + ' days'; } else if ( this.shoppingInterval == 'weekly' || this.shoppingInterval == 'biweekly' || @@ -578,13 +759,46 @@ export class ProfilePage implements OnInit, ViewWillEnter { } else if (this.settings.shoppingIntervalSet === false) { this.settings.shoppingInterval = ''; this.isShoppingModalOpen = isOpen; + } else if ( + this.settings.shoppingIntervalSet === false && + this.shoppingInterval === 'other' + ) { + this.settings.shoppingInterval = ''; + this.isShoppingModalOpen = isOpen; } + this.setInitialShopping(); this.updateSettingsOnServer(); } shoppingInterval_Toggle() { this.settings.shoppingIntervalSet = !this.settings.shoppingIntervalSet; - this.updateSettingsOnServer(); + if (this.settings.shoppingIntervalSet === false) { + this.shoppingInterval = ''; + } + } + + // Function to determine what to display for Shopping Interval + getDisplayShoppingInterval() { + if (this.shoppingInterval === 'other') { + if (this.shoppingIntervalOtherValue.toString().includes('days')) { + return this.shoppingIntervalOtherValue; + } else { + return this.shoppingIntervalOtherValue + ' days'; + } + } else { + return this.settings.shoppingInterval; + } + } + + getDisplayOtherShoppingInterval() { + if (this.shoppingIntervalOtherValue.toString().includes('days')) { + return this.shoppingIntervalOtherValue + .toString() + .replace('days', '') + .trim(); + } else { + return this.shoppingIntervalOtherValue; + } } // Function to update display data @@ -595,7 +809,10 @@ export class ProfilePage implements OnInit, ViewWillEnter { this.settings.shoppingIntervalSet = true; } - if (this.settings.foodPreferences != null) { + if ( + this.settings.foodPreferences != null && + this.settings.foodPreferences.length != 0 + ) { this.preferenceToggle = true; if (this.settings.foodPreferences.includes('Vegetarian')) { this.preferences.vegetarian = true; @@ -633,7 +850,36 @@ export class ProfilePage implements OnInit, ViewWillEnter { this.settings.macroSet = true; } - if (this.settings.allergies != null) { + console.log('budgetupdatedisplay'); + console.log(this.settings.budgetRange); + + // Convert budgetRange to a string to avoid type errors + const budgetString = this.settings.budgetRange + ? this.settings.budgetRange.toString() + : ''; + + // Check for the presence of 'R' and whether it's a custom range + if ( + budgetString.includes('R') && + ['low', 'moderate', 'high'].indexOf( + budgetString.toLowerCase().replace('r ', '') + ) === -1 + ) { + this.budgetToggle = true; + this.selectedPriceRange = 'custom'; + this.settings.budgetSet = true; + console.log('budget- custom'); + } else { + this.budgetToggle = true; + this.selectedPriceRange = budgetString.replace('R ', ''); + this.settings.budgetSet = true; + console.log('budget- not custom'); + } + + if ( + this.settings.allergies != null && + this.settings.allergies.length != 0 + ) { this.allergiesToggle = true; if (this.settings.allergies.includes('Seafood')) { this.allergens.seafood = true; @@ -649,6 +895,7 @@ export class ProfilePage implements OnInit, ViewWillEnter { } this.settings.allergiesSet = true; } + this.settings.allergiesSet = true; if (this.settings.userBMI != 0) { this.BMIToggle = true; @@ -691,4 +938,176 @@ export class ProfilePage implements OnInit, ViewWillEnter { let bmi = this.settings.userWeight / heightSquared; this.settings.userBMI = parseFloat(bmi.toFixed(2)); } + + setInitialShopping() { + this.initialshoppinginterval = this.settings.shoppingInterval; + this.initialshoppingintervalToggle = this.settings.shoppingIntervalSet; + } + + setIntialPreference() { + console.log('Setting Initial Preferences'); + this.initialpreference = this.settings.foodPreferences; + this.initialpreferenceToggle = this.settings.foodPreferenceSet; + this.initialpreferenceVegetarian = this.preferences.vegetarian; + this.initialpreferenceVegan = this.preferences.vegan; + this.initialpreferenceGlutenIntolerant = this.preferences.glutenIntolerant; + this.initialpreferenceLactoseIntolerant = + this.preferences.lactoseIntolerant; + } + + setInitialCalorie() { + this.initialcalorie = this.settings.calorieAmount; + this.initialcalorieToggle = this.settings.calorieSet; + } + + setInitialBudget() { + this.initialbudget = this.settings.budgetRange; + this.initialbudgetToggle = this.settings.budgetSet; + } + + setInitialMacro() { + this.initialprotein = this.settings.protein; + this.initialcarbs = this.settings.carbs; + this.initialfat = this.settings.fat; + this.initialmacroToggle = this.settings.macroSet; + } + + setInitialAllergies() { + this.initialallergiesSeafood = this.allergens.seafood; + this.initialallergiesNuts = this.allergens.nuts; + this.initialallergiesEggs = this.allergens.eggs; + this.initialallergiesSoy = this.allergens.soy; + this.initialallergies = this.settings.allergies; + this.initialallergiesToggle = this.settings.allergiesSet; + } + + setInitialCooking() { + this.initialcooking = this.settings.cookingTime; + this.initialcookingToggle = this.settings.cookingTimeSet; + } + + setInitialBMI() { + this.initialBMI = this.settings.userBMI; + this.initialBMIToggle = this.settings.bmiset; + } + + resetShopping() { + if (this.settings.shoppingInterval.includes('days')) { + const temp = this.settings.shoppingInterval; + this.settings.shoppingInterval = 'other'; + this.shoppingIntervalOtherValue = temp; + } + + this.settings.shoppingInterval = this.initialshoppinginterval; + this.shoppingintervalToggle = this.initialshoppingintervalToggle; + this.settings.shoppingIntervalSet = this.initialshoppingintervalToggle; + this.shoppingInterval = this.initialshoppinginterval; + } + + resetPreference() { + console.log('Resetting Preferences'); + // Reset both settings and preferences objects + this.preferences.vegetarian = this.initialpreferenceVegetarian; + this.preferences.vegan = this.initialpreferenceVegan; + this.preferences.glutenIntolerant = this.initialpreferenceGlutenIntolerant; + this.preferences.lactoseIntolerant = + this.initialpreferenceLactoseIntolerant; + + this.settings.foodPreferences = this.initialpreference; + this.settings.foodPreferenceSet = this.initialpreferenceToggle; + this.preferenceToggle = this.initialpreferenceToggle; + this.displayPreferences = this.initialpreference; + } + + resetCalorie() { + this.settings.calorieAmount = this.initialcalorie; + this.calorieToggle = this.initialcalorieToggle; + this.settings.calorieSet = this.initialcalorieToggle; + } + + resetBudget() { + console.log('resetbudget'); + if (this.initialbudget.includes('R') && this.initialbudgetToggle === true) { + this.settings.budgetRange = this.initialbudget; + this.selectedPriceRange = 'custom'; + this.settings.budgetSet = this.initialbudgetToggle; + this.budgetToggle = this.initialbudgetToggle; + } else if ( + !this.initialbudget.includes('R') && + this.initialbudgetToggle === true + ) { + this.settings.budgetRange = this.initialbudget; + this.selectedPriceRange = this.initialbudget; + this.settings.budgetSet = this.initialbudgetToggle; + this.budgetToggle = this.initialbudgetToggle; + } + } + + resetMacro() { + this.settings.protein = this.initialprotein; + this.settings.carbs = this.initialcarbs; + this.settings.fat = this.initialfat; + this.settings.macroSet = this.initialmacroToggle; + this.macroToggle = this.initialmacroToggle; + this.displaying_Macroratio = this.getDisplayMacroratio(); + } + + resetAllergies() { + this.allergens.seafood = this.initialallergiesSeafood; + this.allergens.nuts = this.initialallergiesNuts; + this.allergens.eggs = this.initialallergiesEggs; + this.allergens.soy = this.initialallergiesSoy; + this.settings.allergies = this.initialallergies; + this.settings.allergiesSet = this.initialallergiesToggle; + this.allergiesToggle = this.initialallergiesToggle; + this.displayAllergies = this.initialallergies; + } + + resetCooking() { + this.settings.cookingTime = this.initialcooking; + this.settings.cookingTimeSet = this.initialcookingToggle; + this.cookingToggle = this.initialcookingToggle; + } + + resetBMI() { + this.settings.userBMI = this.initialBMI; + this.settings.bmiset = this.initialBMIToggle; + this.BMIToggle = this.initialBMIToggle; + } + + disabledConfirmShopping(): boolean { + if (this.settings.shoppingIntervalSet) { + return !this.shoppingInterval; + } + return false; + } + + disabledConfirmPreference(): boolean { + if (this.settings.foodPreferenceSet) { + return !this.displayPreferences; + } + return false; + } + + disabledConfirmBudget(): boolean { + if (this.settings.budgetSet) { + return !this.selectedPriceRange; + } + return false; + } + + disabledCalorieCookingTime(): boolean { + if (this.settings.cookingTimeSet) { + return !this.settings.cookingTime; + } + return false; + } + + async presentToast(message: string) { + const toast = await this.toastController.create({ + message: message, + duration: 2000, + }); + toast.present(); + } } diff --git a/frontend/src/app/pages/recipe-book/recipe-book.page.spec.ts b/frontend/src/app/pages/recipe-book/recipe-book.page.spec.ts index 0fc54835..d5a5d570 100644 --- a/frontend/src/app/pages/recipe-book/recipe-book.page.spec.ts +++ b/frontend/src/app/pages/recipe-book/recipe-book.page.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RecipeBookPage } from './recipe-book.page'; import { AuthenticationService, RecipeBookApiService } from '../../services/services'; +import { HttpClientModule } from '@angular/common/http'; describe('RecipeBookPage', () => { let component: RecipeBookPage; @@ -10,7 +11,7 @@ describe('RecipeBookPage', () => { beforeEach(async() => { await TestBed.configureTestingModule({ - imports: [RecipeBookPage], + imports: [HttpClientModule, RecipeBookPage], providers: [ { provide: RecipeBookApiService, useValue: mockRecipeBookApiService }, { provide: AuthenticationService, useValue: authServiceSpy }, diff --git a/frontend/src/app/pages/recipe-book/recipe-book.page.ts b/frontend/src/app/pages/recipe-book/recipe-book.page.ts index 596a0d8a..5bd04ee1 100644 --- a/frontend/src/app/pages/recipe-book/recipe-book.page.ts +++ b/frontend/src/app/pages/recipe-book/recipe-book.page.ts @@ -22,7 +22,7 @@ import { MealI } from '../../models/meal.model'; export class RecipeBookPage implements OnInit { @ViewChild(RecipeItemComponent) recipeItem!: RecipeItemComponent; public items: MealI[] = []; - + constructor( private recipeService: RecipeBookApiService, private errorHandlerService: ErrorHandlerService, diff --git a/frontend/src/app/pages/signup/signup.page.html b/frontend/src/app/pages/signup/signup.page.html index 3659add0..782c4eae 100644 --- a/frontend/src/app/pages/signup/signup.page.html +++ b/frontend/src/app/pages/signup/signup.page.html @@ -70,7 +70,7 @@ - Sign up + Sign up diff --git a/frontend/src/app/pages/signup/signup.page.ts b/frontend/src/app/pages/signup/signup.page.ts index 8969a4c6..d428abc6 100644 --- a/frontend/src/app/pages/signup/signup.page.ts +++ b/frontend/src/app/pages/signup/signup.page.ts @@ -5,6 +5,8 @@ import { IonicModule } from '@ionic/angular'; import { Router } from '@angular/router'; import { AuthenticationService, ErrorHandlerService } from '../../services/services'; import { UserI } from '../../models/interfaces'; +import { TutorialComponent } from '../../components/tutorial/tutorial.component'; +import { ModalController } from '@ionic/angular'; @Component({ selector: 'app-signup', @@ -22,7 +24,7 @@ export class SignupPage { email: '', } - constructor(private router: Router, private errorHandlerService: ErrorHandlerService, private auth: AuthenticationService ) { } + constructor(private router: Router, private errorHandlerService: ErrorHandlerService, private auth: AuthenticationService,private modalController: ModalController ) { } async signup(form: any) { if (form.initial !== form.verify) { @@ -55,6 +57,13 @@ export class SignupPage { } }); } + async openModal() { + const modal = await this.modalController.create({ + component: TutorialComponent, + }); + + await modal.present(); +} goToLogin() { this.router.navigate(['../']); diff --git a/frontend/src/app/services/barcode-api/barcode-api.service.spec.ts b/frontend/src/app/services/barcode-api/barcode-api.service.spec.ts index e07f0099..3a5ffe56 100644 --- a/frontend/src/app/services/barcode-api/barcode-api.service.spec.ts +++ b/frontend/src/app/services/barcode-api/barcode-api.service.spec.ts @@ -1,13 +1,15 @@ import { TestBed } from '@angular/core/testing'; import { BarcodeApiService } from './barcode-api.service'; +import { HttpClient } from '@angular/common/http'; describe('BarcodeApiService', () => { let service: BarcodeApiService; + let httpClientSpy: jasmine.SpyObj; beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(BarcodeApiService); + service = new BarcodeApiService(httpClientSpy as any); + httpClientSpy = jasmine.createSpyObj('HttpClient', ['post']); }); it('should be created', () => { diff --git a/frontend/src/app/services/like-dislike/like-dislike.service.spec.ts b/frontend/src/app/services/like-dislike/like-dislike.service.spec.ts new file mode 100644 index 00000000..14128dcc --- /dev/null +++ b/frontend/src/app/services/like-dislike/like-dislike.service.spec.ts @@ -0,0 +1,19 @@ +import { TestBed } from '@angular/core/testing'; + +import { LikeDislikeService } from './like-dislike.service'; +import { HttpClientModule } from '@angular/common/http'; + +describe('LikeDislikeService', () => { + let service: LikeDislikeService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientModule] + }); + service = TestBed.inject(LikeDislikeService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/services/like-dislike/like-dislike.service.ts b/frontend/src/app/services/like-dislike/like-dislike.service.ts new file mode 100644 index 00000000..d78cf97f --- /dev/null +++ b/frontend/src/app/services/like-dislike/like-dislike.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { MealI } from '../../models/meal.model'; + +@Injectable({ + providedIn: 'root' +}) +export class LikeDislikeService { + url: String = 'http://localhost:8080'; + + constructor(private http: HttpClient) { } + + liked(item: MealI): Observable> { + return this.http.post( + this.url + '/liked', + { + name: item.name, + description: item.description, + image: item.image, + ingredients: item.ingredients, + instructions: item.instructions, + cookingTime: item.cookingTime, + type: item.type, + }, + { observe: 'response' } + ); + } + + disliked(item: MealI): Observable> { + return this.http.post( + this.url + '/disliked', + { + name: item.name, + description: item.description, + image: item.image, + ingredients: item.ingredients, + instructions: item.instructions, + cookingTime: item.cookingTime, + type: item.type, + }, + { observe: 'response' } + ); + } +} diff --git a/frontend/src/app/services/recipe-book/recipe-book-api.service.ts b/frontend/src/app/services/recipe-book/recipe-book-api.service.ts index 2f44dd01..b5490e9c 100644 --- a/frontend/src/app/services/recipe-book/recipe-book-api.service.ts +++ b/frontend/src/app/services/recipe-book/recipe-book-api.service.ts @@ -1,6 +1,6 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { UserI, RecipeItemI, MealI } from '../../models/interfaces'; +import { UserI, MealI } from '../../models/interfaces'; import { Observable } from 'rxjs'; @Injectable({ diff --git a/frontend/src/app/services/services.ts b/frontend/src/app/services/services.ts index cc9cf886..cc805374 100644 --- a/frontend/src/app/services/services.ts +++ b/frontend/src/app/services/services.ts @@ -7,3 +7,4 @@ export { SettingsApiService } from './settings-api/settings-api.service'; export { MealGenerationService } from './meal-generation/meal-generation.service'; export { LoginService } from './login/login.service'; export { BarcodeApiService } from './barcode-api/barcode-api.service'; +export { LikeDislikeService } from './like-dislike/like-dislike.service'; diff --git a/frontend/src/assets/Browse.jpg b/frontend/src/assets/Browse.jpg new file mode 100644 index 00000000..f2f5192e Binary files /dev/null and b/frontend/src/assets/Browse.jpg differ diff --git a/frontend/src/assets/Final.mp4 b/frontend/src/assets/Final.mp4 new file mode 100644 index 00000000..056f429c Binary files /dev/null and b/frontend/src/assets/Final.mp4 differ diff --git a/frontend/src/assets/Home.jpg b/frontend/src/assets/Home.jpg new file mode 100644 index 00000000..2d2ead09 Binary files /dev/null and b/frontend/src/assets/Home.jpg differ diff --git a/frontend/src/assets/Pantry.jpg b/frontend/src/assets/Pantry.jpg new file mode 100644 index 00000000..d422470e Binary files /dev/null and b/frontend/src/assets/Pantry.jpg differ diff --git a/frontend/src/assets/Recipe book.jpg b/frontend/src/assets/Recipe book.jpg new file mode 100644 index 00000000..745cb2c2 Binary files /dev/null and b/frontend/src/assets/Recipe book.jpg differ diff --git a/frontend/src/assets/homeTut.mp4 b/frontend/src/assets/homeTut.mp4 new file mode 100644 index 00000000..7cfc5bbb Binary files /dev/null and b/frontend/src/assets/homeTut.mp4 differ diff --git a/frontend/src/assets/modal.jpg b/frontend/src/assets/modal.jpg new file mode 100644 index 00000000..6f1d9bd0 Binary files /dev/null and b/frontend/src/assets/modal.jpg differ diff --git a/frontend/src/assets/preferences.jpg b/frontend/src/assets/preferences.jpg new file mode 100644 index 00000000..8a4b6cc7 Binary files /dev/null and b/frontend/src/assets/preferences.jpg differ diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss new file mode 100644 index 00000000..e69de29b diff --git a/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png index adf6ba01..9048530e 100644 Binary files a/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png and b/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/package-lock.json b/package-lock.json index b981493c..3117e1c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,14 +26,15 @@ "@capacitor/status-bar": "^5.0.4", "@ionic/angular": "^7.0.0", "@types/chart.js": "^2.9.37", + "@types/swiper": "^6.0.0", "chart.js": "^4.3.0", - "cordova-plugin-advanced-http": "^3.3.1", "cordova-plugin-file": "^8.0.0", "dotenv": "^16.3.1", "ionicons": "^7.0.0", "neo4j-driver": "^5.10.0", "openai": "^3.3.0", "rxjs": "~7.5.0", + "swiper": "^10.3.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" }, @@ -254,6 +255,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/@angular-devkit/build-angular/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, "node_modules/@angular-devkit/build-webpack": { "version": "0.1502.9", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1502.9.tgz", @@ -715,9 +722,9 @@ "dev": true }, "node_modules/@awesome-cordova-plugins/core": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/core/-/core-6.3.0.tgz", - "integrity": "sha512-MkcWO8akZLHa2RSJEPf76Y3P9wPqh5oXE8YCzn2vnYYeNyYWYnka2pHFsgUdbXJNiS+YeveUzvw+Isweg+wynA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/core/-/core-6.4.0.tgz", + "integrity": "sha512-06I5JdTgAgKTby+VG+3sQF5+z4RNCEyVl6y7tz2rICx8MURL1biuh3oGGN1rCQQjsuMZcX5siMBr0NF/OHqxLQ==", "peer": true, "dependencies": { "@types/cordova": "latest" @@ -727,9 +734,9 @@ } }, "node_modules/@awesome-cordova-plugins/http": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/http/-/http-6.3.0.tgz", - "integrity": "sha512-RmQaMZ/8aw5q0uQWm6ojfzKO3mjJOxM0IUm63Rxj/khrS6Acq/mKo4UMhgDmBB9Uai0Hj6/VJVe0YvbmKueaVw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/http/-/http-6.4.0.tgz", + "integrity": "sha512-nv8Az1bYnEm/MQSA6Oec0FFAGFu5bmubQXypp08ZUJA4uGkps3IJS02F0451PF/vM0Jcpnb+W6ZRqRCNJ34ZJA==", "dependencies": { "@types/cordova": "latest" }, @@ -739,21 +746,22 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", - "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -839,34 +847,63 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.21.5.tgz", - "integrity": "sha512-uNrjKztPLkUk7bpCNC0jEKDJzzkvel/W+HguzbN8krA+LPfC1CEobJEvAvGka2A/M+ViOqXdcRL0GqPUJSjx9g==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", + "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", - "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.5", + "@babel/compat-data": "^7.22.9", "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.3", + "browserslist": "^4.21.9", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { @@ -879,9 +916,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz", - "integrity": "sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.11.tgz", + "integrity": "sha512-y1grdYL4WzmUDBRGK0pDbIoFd7UZKoDurDzWEoNMYoj1EL+foGRQNyPWDcC+YyegN5y1DUsFFmzjGijB3nSVAQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -889,10 +926,10 @@ "@babel/helper-function-name": "^7.22.5", "@babel/helper-member-expression-to-functions": "^7.22.5", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "semver": "^6.3.0" + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -914,9 +951,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", - "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { "@babel/types": "^7.22.5" @@ -935,14 +972,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz", - "integrity": "sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "regexpu-core": "^5.3.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -1059,31 +1096,43 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", - "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1111,15 +1160,14 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz", - "integrity": "sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-wrap-function": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-wrap-function": "^7.22.9" }, "engines": { "node": ">=6.9.0" @@ -1141,43 +1189,29 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz", - "integrity": "sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-member-expression-to-functions": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers/node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1235,15 +1269,14 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz", - "integrity": "sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", + "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", "dev": true, "dependencies": { "@babel/helper-function-name": "^7.22.5", "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.10" }, "engines": { "node": ">=6.9.0" @@ -1264,27 +1297,41 @@ } }, "node_modules/@babel/helpers": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", - "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz", + "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.11", + "@babel/types": "^7.22.11" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { + "node_modules/@babel/helpers/node_modules/@babel/template": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -1292,9 +1339,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", - "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz", + "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1551,9 +1598,9 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", - "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", @@ -1648,12 +1695,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1777,12 +1824,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz", - "integrity": "sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.21.5" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1809,12 +1856,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1824,12 +1871,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", + "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1839,19 +1886,19 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.5.tgz", - "integrity": "sha512-2edQhLfibpWpsVBx2n/GKOz6JdGQvLruZQfGr9l1qes2KQaWswjBzhQF7UDUZMNaMMQeYnQzxwOMPsbYF7wqPQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-replace-supers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, "engines": { @@ -1874,9 +1921,9 @@ } }, "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", - "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { "@babel/types": "^7.22.5" @@ -1886,13 +1933,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz", - "integrity": "sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.21.5", - "@babel/template": "^7.20.7" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1901,13 +1948,27 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", + "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1917,13 +1978,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1933,12 +1994,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1948,13 +2009,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1964,12 +2025,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz", - "integrity": "sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.21.5" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1996,12 +2057,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2011,12 +2072,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2026,13 +2087,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2042,14 +2103,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz", - "integrity": "sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.11.tgz", + "integrity": "sha512-o2+bg7GDS60cJMgz9jWqRUsWkMzLCxp+jFDeDUT5sjRlAxcJWZ2ylNdI7QQ2+CH5hWu7OnN+Cv3htt7AkSf96g==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helper-plugin-utils": "^7.21.5", - "@babel/helper-simple-access": "^7.21.5" + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2059,15 +2120,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz", + "integrity": "sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2077,13 +2138,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2109,12 +2170,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2124,13 +2185,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2140,9 +2201,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.5.tgz", - "integrity": "sha512-AconbMKOMkyG+xCng2JogMCDcqW8wedQAqpVIL4cOSescZ7+iW8utC6YDZLMCSUIReEA733gzRSaOSXMAt/4WQ==", + "version": "7.22.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.12.tgz", + "integrity": "sha512-7XXCVqZtyFWqjDsYDY4T45w4mlx1rf7aOgkc/Ww76xkgBiOlmjPkx36PBLHa1k1rwWvVgYMPsbuVnIamx2ZQJw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2157,12 +2218,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2172,12 +2233,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2187,13 +2248,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz", - "integrity": "sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.21.5", - "regenerator-transform": "^0.15.1" + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -2203,12 +2264,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2247,12 +2308,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2262,13 +2323,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2278,12 +2339,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2293,12 +2354,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2308,12 +2369,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2323,12 +2384,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.21.5.tgz", - "integrity": "sha512-LYm/gTOwZqsYohlvFUe/8Tujz75LqqVC2w+2qPHLR+WyWHGCZPN1KBpJCJn+4Bk4gOkQy/IXKIge6az5MqwlOg==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.21.5" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2338,13 +2399,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -2452,9 +2513,9 @@ } }, "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -2464,7 +2525,7 @@ "esutils": "^2.0.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/regjsgen": { @@ -2500,19 +2561,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", - "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz", + "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.11", + "@babel/types": "^7.22.11", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2521,12 +2582,12 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", - "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.22.10", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -2536,9 +2597,9 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", - "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { "@babel/types": "^7.22.5" @@ -2562,9 +2623,9 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz", + "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", @@ -2641,97 +2702,28 @@ "node": ">=16.0.0" } }, - "node_modules/@capacitor/cli/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, + "node_modules/@capacitor/core": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.0.5.tgz", + "integrity": "sha512-sulwWXEhYI6cBIj1WnH9k+a8z1f4XTRDtdh3YfXNdeV36UT7T55GCeGrPoQMm7ww6iWyGuv1VEzVIuZFga8rtw==", "dependencies": { - "balanced-match": "^1.0.0" + "tslib": "^2.1.0" } }, - "node_modules/@capacitor/cli/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" + "node_modules/@capacitor/haptics": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-5.0.4.tgz", + "integrity": "sha512-gcldLYE517h7t/r9oK1J7EV6hX854gjZNiDrS5j5O91V193L2K43Yqyp2ZKfdZ05ZLTBYkr/vg1ZTScfHseLxg==", + "peerDependencies": { + "@capacitor/core": "^5.0.0" } }, - "node_modules/@capacitor/cli/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, + "node_modules/@capacitor/http": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/http/-/http-0.0.2.tgz", + "integrity": "sha512-3UPqYOmVkAQjCWWowSDGPnBkXY7znbPE7lNs8nhwTmE2E5fXTvjHM8PV15zOyn+nenY7zEu9Air49fGjrX+Tjg==", "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@capacitor/cli/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@capacitor/cli/node_modules/rimraf": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", - "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", - "dev": true, - "dependencies": { - "glob": "^9.2.0" - }, - "bin": { - "rimraf": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@capacitor/core": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.0.5.tgz", - "integrity": "sha512-sulwWXEhYI6cBIj1WnH9k+a8z1f4XTRDtdh3YfXNdeV36UT7T55GCeGrPoQMm7ww6iWyGuv1VEzVIuZFga8rtw==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@capacitor/haptics": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-5.0.4.tgz", - "integrity": "sha512-gcldLYE517h7t/r9oK1J7EV6hX854gjZNiDrS5j5O91V193L2K43Yqyp2ZKfdZ05ZLTBYkr/vg1ZTScfHseLxg==", - "peerDependencies": { - "@capacitor/core": "^5.0.0" - } - }, - "node_modules/@capacitor/http": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@capacitor/http/-/http-0.0.2.tgz", - "integrity": "sha512-3UPqYOmVkAQjCWWowSDGPnBkXY7znbPE7lNs8nhwTmE2E5fXTvjHM8PV15zOyn+nenY7zEu9Air49fGjrX+Tjg==", - "dependencies": { - "@capacitor/core": "latest" + "@capacitor/core": "latest" } }, "node_modules/@capacitor/ios": { @@ -3165,9 +3157,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3206,12 +3198,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, "node_modules/@humanwhocodes/config-array": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", @@ -3233,11 +3219,11 @@ "dev": true }, "node_modules/@ionic/angular": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.0.5.tgz", - "integrity": "sha512-seTyc70JGPrIOn1LjviFfWT8T5aMdj3J97BdOyWU7TFqyapTwj6Rn7x2OyeV9Rph7wcA9Sz3PD1FBwPEuj5utw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.3.1.tgz", + "integrity": "sha512-eOrqEYanyDiW5L9uk2O2CR/dsoZ5INfk6HtgIp4FtDODq0bnTiyXS9OSBbgFan4UOptY7BZzT7kepj7PBI76cQ==", "dependencies": { - "@ionic/core": "7.0.5", + "@ionic/core": "7.3.1", "ionicons": "^7.0.0", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -3276,15 +3262,35 @@ } }, "node_modules/@ionic/core": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.0.5.tgz", - "integrity": "sha512-dcuE/PEF+GHsPEsLppUASSwWnzVcxFZE7uPMDzTwUPMOFTTaRgWbPxIly/4/VRbV6GSL6MEcuVVxhEdWjSODTg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.3.1.tgz", + "integrity": "sha512-RdSJsFYx2oJ08duw+DMWVAfzjxlnA+o1saX5gOLSjP5SpwP7FqURFfXrFHIFN2vIKbeqUZTZjQwPHnrFsX04dQ==", "dependencies": { - "@stencil/core": "^3.2.2", - "ionicons": "^7.1.0", + "@stencil/core": "^4.1.0", + "ionicons": "7.1.0", "tslib": "^2.1.0" } }, + "node_modules/@ionic/core/node_modules/ionicons": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.0.tgz", + "integrity": "sha512-iE4GuEdEHARJpp0sWL7WJZCzNCf5VxpNRhAjW0fLnZPnNL5qZOJUcfup2Z2Ty7Jk8Q5hacrHfGEB1lCwOdXqGg==", + "dependencies": { + "@stencil/core": "^2.18.0" + } + }, + "node_modules/@ionic/core/node_modules/ionicons/node_modules/@stencil/core": { + "version": "2.22.3", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.22.3.tgz", + "integrity": "sha512-kmVA0M/HojwsfkeHsifvHVIYe4l5tin7J5+DLgtl8h6WWfiMClND5K3ifCXXI2ETDNKiEk21p6jql3Fx9o2rng==", + "bin": { + "stencil": "bin/stencil" + }, + "engines": { + "node": ">=12.10.0", + "npm": ">=6.0.0" + } + }, "node_modules/@ionic/utils-array": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.6.tgz", @@ -3313,42 +3319,6 @@ "node": ">=16.0.0" } }, - "node_modules/@ionic/utils-fs/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@ionic/utils-fs/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@ionic/utils-fs/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@ionic/utils-object": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@ionic/utils-object/-/utils-object-2.1.6.tgz", @@ -3496,9 +3466,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { "ansi-regex": "^6.0.1" @@ -3566,9 +3536,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, "engines": { "node": ">=6.0.0" @@ -3584,9 +3554,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", @@ -3614,21 +3584,15 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", @@ -3704,9 +3668,9 @@ } }, "node_modules/@npmcli/git": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.0.4.tgz", - "integrity": "sha512-5yZghx+u5M47LghaybLCkdSyFzV/w4OuH12d96HO389Ik9CDsLaDZJVynSGGVJOLn6gy/k7Dz5XYcplM3uxXRg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", "dev": true, "dependencies": { "@npmcli/promise-spawn": "^6.0.0", @@ -3762,32 +3726,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@npmcli/node-gyp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", @@ -3881,11 +3819,50 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/@sigstore/protobuf-specs": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", - "integrity": "sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -3897,15 +3874,15 @@ "dev": true }, "node_modules/@stencil/core": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-3.2.2.tgz", - "integrity": "sha512-wXb9cVWL0T3cTwYLveekdTFCRGx6+9hpVDEXna+N8K8OPoW6xtFAHRLv+LjOM7k59PkA8MG3IinAfV7Y+xa0Hw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.1.0.tgz", + "integrity": "sha512-yIpL+CX02fy5zvFXwXcHZjjEILRm3aiONbucpfLIWPS7zcBAuucdROssartEa+D7E1JRko97ydxn1Ntdu4GoWg==", "bin": { "stencil": "bin/stencil" }, "engines": { - "node": ">=14.10.0", - "npm": ">=6.0.0" + "node": ">=16.0.0", + "npm": ">=7.10.0" } }, "node_modules/@tootallnate/once": { @@ -3949,9 +3926,9 @@ } }, "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -4030,9 +4007,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", "dev": true, "dependencies": { "@types/estree": "*", @@ -4068,9 +4045,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "version": "4.17.36", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", + "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", "dev": true, "dependencies": { "@types/node": "*", @@ -4110,9 +4087,9 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/json5": { @@ -4208,6 +4185,15 @@ "@types/node": "*" } }, + "node_modules/@types/swiper": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/swiper/-/swiper-6.0.0.tgz", + "integrity": "sha512-QPZRgxZ+ivXXtzV43B3LxpXUIC7FE/EoKM+rtxngmgt2M7eeUYypZhyqZD8UxJtlBcUDw/ATGoVeSNpvBBrz2w==", + "deprecated": "This is a stub types definition. swiper provides its own type definitions, so you do not need this installed.", + "dependencies": { + "swiper": "*" + } + }, "node_modules/@types/ws": { "version": "8.5.5", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", @@ -4748,6 +4734,15 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -4852,13 +4847,11 @@ } }, "node_modules/agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", "dev": true, "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { @@ -5111,6 +5104,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -5355,6 +5368,30 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -5475,10 +5512,9 @@ } }, "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -5495,7 +5531,7 @@ ], "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ieee754": "^1.2.1" } }, "node_modules/buffer-crc32": { @@ -5596,9 +5632,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001486", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", - "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==", + "version": "1.0.30001524", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz", + "integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==", "dev": true, "funding": [ { @@ -5636,9 +5672,9 @@ "dev": true }, "node_modules/chart.js": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.0.tgz", - "integrity": "sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", + "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -5790,15 +5826,6 @@ "node": ">=4.0" } }, - "node_modules/codecov/node_modules/ignore-walk": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", - "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.4" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -5850,10 +5877,13 @@ } }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } }, "node_modules/comment-parser": { "version": "0.7.6", @@ -6081,14 +6111,14 @@ } }, "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "dependencies": { "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", "merge2": "^1.4.1", "slash": "^4.0.0" }, @@ -6111,17 +6141,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cordova-plugin-advanced-http": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/cordova-plugin-advanced-http/-/cordova-plugin-advanced-http-3.3.1.tgz", - "integrity": "sha512-hESuB3mxIHCUrzb5lm7juda6PSNcC5N8Invizj5wGV2rSldCapiNxMTEpzKR1UVPDDP2XOtBzO0SAYS+3+g/ig==", - "engines": [ - { - "name": "cordova", - "version": ">=4.0.0" - } - ] - }, "node_modules/cordova-plugin-file": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-8.0.0.tgz", @@ -6144,22 +6163,54 @@ } }, "node_modules/core-js-compat": { - "version": "3.30.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.2.tgz", - "integrity": "sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA==", + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.1.tgz", + "integrity": "sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==", "dev": true, "dependencies": { - "browserslist": "^4.21.5" + "browserslist": "^4.21.10" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "node_modules/core-js-compat/node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, "node_modules/cors": { @@ -6388,15 +6439,15 @@ } }, "node_modules/deep-equal": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", - "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.0", + "get-intrinsic": "^1.2.1", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", @@ -6553,9 +6604,9 @@ "dev": true }, "node_modules/dns-packet": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", - "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" @@ -6667,9 +6718,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.385", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.385.tgz", - "integrity": "sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg==", + "version": "1.4.503", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.503.tgz", + "integrity": "sha512-LF2IQit4B0VrUHFeQkWhZm97KuJSGF2WJqq1InpY+ECpFRkXd8yTIaTtJxsO0OKDmiBYwWqcrNaXOurn2T2wiA==", "dev": true }, "node_modules/elementtree": { @@ -6684,12 +6735,6 @@ "node": ">= 0.4.0" } }, - "node_modules/elementtree/node_modules/sax": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", - "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", - "dev": true - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -6738,9 +6783,9 @@ } }, "node_modules/engine.io": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz", - "integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -6751,26 +6796,26 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", + "engine.io-parser": "~5.2.1", "ws": "~8.11.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", - "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", "dev": true, "engines": { "node": ">=10.0.0" } }, "node_modules/enhanced-resolve": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", - "integrity": "sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -6781,12 +6826,13 @@ } }, "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -6845,18 +6891,19 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", + "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", @@ -6876,14 +6923,18 @@ "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", "safe-regex-test": "^1.0.0", "string.prototype.trim": "^1.2.7", "string.prototype.trimend": "^1.0.6", "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -7090,14 +7141,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -7109,6 +7160,23 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -7227,9 +7295,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -7270,9 +7338,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -7423,9 +7491,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -7616,6 +7684,12 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -7793,9 +7867,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -7980,16 +8054,52 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.7", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/flatted": { @@ -8043,9 +8153,9 @@ } }, "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", - "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { "node": ">=14" @@ -8077,9 +8187,9 @@ } }, "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz", + "integrity": "sha512-/KxoyCnPM0GwYI4NN0Iag38Tqt+od3/mLuguepLgCAKPn0ZhC544nssAW0tG2/00zXEYl9W+7hwAIpLHo6Oc7Q==", "dev": true, "engines": { "node": "*" @@ -8099,44 +8209,45 @@ } }, "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "dependencies": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=10" } }, "node_modules/fs-minipass": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", - "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs-minipass/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", "dev": true }, "node_modules/fs.realpath": { @@ -8146,9 +8257,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -8236,13 +8347,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -8786,39 +8898,12 @@ } }, "node_modules/ignore-walk": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", - "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", - "dev": true, - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "minimatch": "^3.0.4" } }, "node_modules/image-size": { @@ -8835,9 +8920,9 @@ } }, "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", "dev": true }, "node_modules/import-fresh": { @@ -8883,12 +8968,6 @@ "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -9025,9 +9104,9 @@ } }, "node_modules/ionicons": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.0.tgz", - "integrity": "sha512-iE4GuEdEHARJpp0sWL7WJZCzNCf5VxpNRhAjW0fLnZPnNL5qZOJUcfup2Z2Ty7Jk8Q5hacrHfGEB1lCwOdXqGg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.2.tgz", + "integrity": "sha512-zZ4njAqSP39H8RRvZhJvkHsv7cBjYE/VfInH218Osf2UVxJITSOutTTd25MW+tAXKN5fheYzclUXUsF55JHUDg==", "dependencies": { "@stencil/core": "^2.18.0" } @@ -9148,9 +9227,9 @@ } }, "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -9383,16 +9462,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.11" }, "engines": { "node": ">= 0.4" @@ -9533,17 +9608,17 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-report/node_modules/has-flag": { @@ -9555,6 +9630,21 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/istanbul-lib-report/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -9591,9 +9681,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -9604,9 +9694,9 @@ } }, "node_modules/jackspeak": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz", - "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", + "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -9717,6 +9807,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -9753,10 +9849,13 @@ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -10025,6 +10124,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/karma/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/karma/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10061,6 +10175,15 @@ "node": ">=10" } }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -10462,161 +10585,49 @@ "dev": true }, "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" + "ssri": "^10.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/make-fetch-happen/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -10627,12 +10638,12 @@ } }, "node_modules/memfs": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.1.tgz", - "integrity": "sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dev": true, "dependencies": { - "fs-monkey": "^1.0.3" + "fs-monkey": "^1.0.4" }, "engines": { "node": ">= 4.0.0" @@ -10807,40 +10818,31 @@ "dev": true }, "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", "dev": true, "dependencies": { - "minipass": "^3.1.6", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/minipass-fetch/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", @@ -11125,6 +11127,13 @@ "node": ">=0.10.0" } }, + "node_modules/needle/node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "optional": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -11141,52 +11150,29 @@ "dev": true }, "node_modules/neo4j-driver": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/neo4j-driver/-/neo4j-driver-5.10.0.tgz", - "integrity": "sha512-xvexTGrMxS3Nj/vU/OO5FA0wMcmdOJOOqHgztydw8iSFnKBgxxAo3giiH1UKGwP4k12BnOSXSQeZGXT3faVHJQ==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/neo4j-driver/-/neo4j-driver-5.11.0.tgz", + "integrity": "sha512-2IPKXH9najfKJyczIZ8R15p/oYsb4P+nwp76XRjO46Zl+ssc22+gMe/8FLRYw3tRJYc3b87ikx2s8ZNuseOAxQ==", "dependencies": { - "neo4j-driver-bolt-connection": "5.10.0", - "neo4j-driver-core": "5.10.0", + "neo4j-driver-bolt-connection": "5.11.0", + "neo4j-driver-core": "5.11.0", "rxjs": "^7.8.1" } }, "node_modules/neo4j-driver-bolt-connection": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/neo4j-driver-bolt-connection/-/neo4j-driver-bolt-connection-5.10.0.tgz", - "integrity": "sha512-TgxaQ1kRtd4hP2iromtun3twx+tLP9I0F7CIhDpYaUix8Z1nHcI6z9y+uJ1+YU/doyzgS+R/ZP8h2C4S75iClw==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/neo4j-driver-bolt-connection/-/neo4j-driver-bolt-connection-5.11.0.tgz", + "integrity": "sha512-jfptm6W/a4CIoip4S/KubxrPIIV3hdOJ8B5t2RtMJwVfup8uJFzRsQLW/ljg7PJdMiE1hHQ94/qcVKd3gCC3og==", "dependencies": { "buffer": "^6.0.3", - "neo4j-driver-core": "5.10.0", + "neo4j-driver-core": "5.11.0", "string_decoder": "^1.3.0" } }, - "node_modules/neo4j-driver-bolt-connection/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/neo4j-driver-core": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/neo4j-driver-core/-/neo4j-driver-core-5.10.0.tgz", - "integrity": "sha512-Wf50GRvEqG2R0PWMJg3tF7YxILJb4QjYgpoC7g/2OCjmQQUuSy+wj65aUlV66XB4I9J07FElGWy6Xrm/rDyA5A==" + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/neo4j-driver-core/-/neo4j-driver-core-5.11.0.tgz", + "integrity": "sha512-HIZrX1wIkwb1BlXtDk0thbyzYrlDKQK9PuzcgeKF9/fTORxr5K39kdIiwVi3gkoGOcFCSoBu+fTnlnav1BcgRg==" }, "node_modules/neo4j-driver/node_modules/rxjs": { "version": "7.8.1", @@ -11219,9 +11205,9 @@ "optional": true }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -11248,15 +11234,16 @@ } }, "node_modules/node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", + "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", "dev": true, "dependencies": { "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", + "make-fetch-happen": "^11.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", @@ -11272,9 +11259,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", "dev": true, "optional": true, "bin": { @@ -11303,10 +11290,25 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, "node_modules/nopt": { @@ -11370,9 +11372,9 @@ } }, "node_modules/npm-install-checks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.1.1.tgz", - "integrity": "sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz", + "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==", "dev": true, "dependencies": { "semver": "^7.1.1" @@ -11417,6 +11419,42 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-packlist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm-packlist/node_modules/ignore-walk": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", + "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", + "dev": true, + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-packlist/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/npm-pick-manifest": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", @@ -11450,41 +11488,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-registry-fetch/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/npm-registry-fetch/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -11494,23 +11497,6 @@ "node": ">=8" } }, - "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "dev": true, - "dependencies": { - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -11612,14 +11598,14 @@ } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -12106,13 +12092,13 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", - "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, "dependencies": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -12122,21 +12108,21 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", - "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "dev": true, "engines": { "node": "14 || >=16.14" } }, "node_modules/path-scurry/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/path-to-regexp": { @@ -12214,16 +12200,17 @@ } }, "node_modules/plist": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz", - "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "dependencies": { + "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" }, "engines": { - "node": ">=6" + "node": ">=10.4.0" } }, "node_modules/postcss": { @@ -12285,9 +12272,9 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", "dev": true, "dependencies": { "icss-utils": "^5.0.0", @@ -12332,9 +12319,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", - "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -12552,9 +12539,9 @@ } }, "node_modules/read-package-json": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.3.tgz", - "integrity": "sha512-4QbpReW4kxFgeBQ0vPAqh2y8sXEB3D4t3jsXbJKIhBiF80KT6XRo45reqwtftju5J6ru1ax06A2Gb/wM1qCOEQ==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", "dev": true, "dependencies": { "glob": "^10.2.2", @@ -12598,16 +12585,16 @@ } }, "node_modules/read-package-json/node_modules/glob": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", - "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.0.3", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.7.0" + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { "glob": "dist/cjs/src/bin.js" @@ -12629,9 +12616,9 @@ } }, "node_modules/read-package-json/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -12644,12 +12631,12 @@ } }, "node_modules/read-package-json/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/read-pkg": { @@ -12842,9 +12829,9 @@ "dev": true }, "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" @@ -13060,35 +13047,60 @@ "dev": true }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "glob": "^9.2.0" }, "bin": { - "rimraf": "bin.js" + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -13134,6 +13146,24 @@ "tslib": "^2.1.0" } }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -13229,15 +13259,15 @@ } }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", "dev": true }, "node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", @@ -13529,14 +13559,16 @@ "dev": true }, "node_modules/sigstore": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.4.0.tgz", - "integrity": "sha512-N7TRpSbFjY/TrFDg6yGAQSYBrQ5s6qmPiq4pD6fkv1LoyfMsLG0NwZWG2s5q+uttLHgyVyTa0Rogx2P78rN8kQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", "dev": true, "dependencies": { - "@sigstore/protobuf-specs": "^0.1.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" }, "bin": { "sigstore": "bin/sigstore.js" @@ -13545,67 +13577,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/sigstore/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/sigstore/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/sigstore/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sigstore/node_modules/minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "dev": true, - "dependencies": { - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -13682,20 +13653,21 @@ } }, "node_modules/socket.io": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", - "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", + "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.4.1", + "engine.io": "~6.5.2", "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.1" + "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { @@ -13907,24 +13879,24 @@ "dev": true }, "node_modules/ssri": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", - "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", "dev": true, "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/ssri/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/statuses": { @@ -13971,6 +13943,38 @@ "node": ">=8.0" } }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -14138,6 +14142,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swiper": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-10.3.0.tgz", + "integrity": "sha512-o81KZH4phL/dJxKFWpZ/zf78QxOyFMood+c86vJJO0ZeSOoniyzV8HWDsw12KOlQdm4WRxrc/6kfGImAcxcS3w==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", @@ -14173,9 +14195,9 @@ } }, "node_modules/tar": { - "version": "6.1.14", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.14.tgz", - "integrity": "sha512-piERznXu0U7/pW7cdSn7hjqySIVTYT6F76icmFk7ptU7dDYlXTm5r9A6K04R2vU3olYgoKeo1Cg3eeu5nhftAw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dev": true, "dependencies": { "chownr": "^2.0.0", @@ -14298,9 +14320,9 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.8.tgz", - "integrity": "sha512-WiHL3ElchZMsK27P8uIUh4604IgJyAW47LVXGbEoB21DbQcZ+OuMpGjVYnEUaqcWM6dO8uS2qUbA7LSCWqvsbg==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", @@ -14332,9 +14354,9 @@ } }, "node_modules/terser-webpack-plugin/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -14368,6 +14390,12 @@ "ajv": "^6.9.1" } }, + "node_modules/terser-webpack-plugin/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -14375,9 +14403,9 @@ "dev": true }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -14393,13 +14421,13 @@ } }, "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.17.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.2.tgz", - "integrity": "sha512-1D1aGbOF1Mnayq5PvfMc0amAR1y5Z1nrZaGCvI5xsdEfZEVte8okonk02OiaK5fw5hG1GWuuVsakOnpZW8y25A==", + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -14411,9 +14439,9 @@ } }, "node_modules/terser/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -14422,6 +14450,12 @@ "node": ">=0.4.0" } }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -14495,6 +14529,41 @@ "node": ">=8.17.0" } }, + "node_modules/tmp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tmp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -14587,9 +14656,9 @@ } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -14613,77 +14682,17 @@ "dev": true }, "node_modules/tuf-js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.5.tgz", - "integrity": "sha512-inqodgxdsmuxrtQVbu6tPNgRKWD1Boy3VB6GO7KczJZpAHiTukwhSzXUSzvDcw5pE2Jo8ua+e1ykpHv7VdPVlQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", "dev": true, "dependencies": { "@tufjs/models": "1.0.4", - "make-fetch-happen": "^11.1.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/tuf-js/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/tuf-js/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "dev": true, - "dependencies": { - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" } }, "node_modules/type-check": { @@ -14723,6 +14732,57 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", @@ -14855,12 +14915,12 @@ } }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -14954,9 +15014,9 @@ } }, "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", "dev": true }, "node_modules/validate-npm-package-license": { @@ -15161,6 +15221,41 @@ } } }, + "node_modules/webpack-dev-server/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/webpack-dev-server/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", @@ -15228,9 +15323,9 @@ } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -15240,9 +15335,9 @@ } }, "node_modules/webpack/node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, "peerDependencies": { "acorn": "^8" @@ -15302,9 +15397,9 @@ "dev": true }, "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -15399,17 +15494,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index 936d32f6..802205de 100644 --- a/package.json +++ b/package.json @@ -33,14 +33,15 @@ "@capacitor/status-bar": "^5.0.4", "@ionic/angular": "^7.0.0", "@types/chart.js": "^2.9.37", + "@types/swiper": "^6.0.0", "chart.js": "^4.3.0", - "cordova-plugin-advanced-http": "^3.3.1", "cordova-plugin-file": "^8.0.0", "dotenv": "^16.3.1", "ionicons": "^7.0.0", "neo4j-driver": "^5.10.0", "openai": "^3.3.0", "rxjs": "~7.5.0", + "swiper": "^10.3.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" }, diff --git a/readme.md b/readme.md index 3ff09b5a..ead99d99 100644 --- a/readme.md +++ b/readme.md @@ -15,52 +15,38 @@ substitutions, budget preferences and gives users the ability to add ingredients virtual pantry through image recognition. It aims to reduce decision fatigue, helps users easily plan meals for the coming week and helps them hit their nutritional goals. -# Set Up -## Install: -- Node v18.16.0 -- npm v9.5.1 -- Angular CLI v16.0.0 -- Ionic CLI v7.1.1 -- Gradle v8 - -## Install prerequisites: - -1. Install Node.js (https://nodejs.org/) and npm (comes with Node.js). -2. Install Angular CLI globally by running `npm install -g @angular/cli` -3. Install Ionic CLI globally by running `npm install -g @ionic/cli` -4. Install Gradle (https://gradle.org/install/) - -## Starting the app: -1. Will most likely need to run `npm install` to install all dependencies. -2. Run `ionic serve` to start the app in the browser. -3. Run `.\backend\gradlew.bat -p backend bootRun` to start the backend server. -4. Frontend will be running on http://localhost:8100/ and the backend will be running on http://localhost:8080/ - # Documentation ## Demo 1 -- 🎥 https://drive.google.com/file/d/10Eq8U3jkWRM08BBfeC6RolvX8edsNR31/view?usp=sharing - -## System Requirements Specification -### v1: - -- 📃 https://docs.google.com/document/d/1r36yfCPophZftvO_4PcoFPyaN1UonBcP5Fbmt0ypGoI/edit?usp=sharing -### v2: - -- 📃 https://docs.google.com/document/d/1FmSqFAENVQOZEEr14x5cBBWr9sgkA5lm3mrld0XY0l8/edit?usp=sharing - -## User Manual Document -- 📃 https://docs.google.com/document/d/1Cvxc9UgSUuXDbWwugPlxlK7Dh_KO7xvwuzCKtDzu1sM/edit?usp=sharing - -## Coding Standards Document -- 📃 https://docs.google.com/document/d/1Prh1NJkLCubiySVKyEGGlkWgBTonqnkokMo-sBYGPYw/edit?usp=sharing - -## Architectural Requirements Document -- 📃 https://docs.google.com/document/d/1GADUq8VWsgqLFTfSPIBHwsFnrli8AbZGp7uwuRqVZu8/edit?usp=sharing - -## Project Board - -- 📋 https://github.com/orgs/COS301-SE-2023/projects/38 +- 🎥 [Demo 1](https://drive.google.com/file/d/10Eq8U3jkWRM08BBfeC6RolvX8edsNR31/view?usp=sharing) +### System Requirements Specification +- 📃 [SRS](https://docs.google.com/document/d/1r36yfCPophZftvO_4PcoFPyaN1UonBcP5Fbmt0ypGoI/edit?usp=sharing) + + +## Demo 2 +### System Requirements Specification +- 📃 [SRS](https://docs.google.com/document/d/1FmSqFAENVQOZEEr14x5cBBWr9sgkA5lm3mrld0XY0l8/edit?usp=sharing) +### User Manual Document +- 📃 [User Manual](https://docs.google.com/document/d/1Cvxc9UgSUuXDbWwugPlxlK7Dh_KO7xvwuzCKtDzu1sM/edit?usp=sharing) +### Coding Standards Document +- 📃 [Coding Standards](https://docs.google.com/document/d/1Prh1NJkLCubiySVKyEGGlkWgBTonqnkokMo-sBYGPYw/edit?usp=sharing) +### Architectural Requirements Document +- 📃 [Architectural Requirements](https://docs.google.com/document/d/1GADUq8VWsgqLFTfSPIBHwsFnrli8AbZGp7uwuRqVZu8/edit?usp=sharing) + + +## Demo 3 +### System Requirements Specification +- 📃 [SRS](https://docs.google.com/document/d/1FmSqFAENVQOZEEr14x5cBBWr9sgkA5lm3mrld0XY0l8/edit?usp=sharing) +### Technical Installation Manual +- 📖 [Installation Manual](https://docs.google.com/document/d/1KWnnRnpyYKyQDBUFijPwVD7MgGMjvhL-w9v_T77EAyE/edit?usp=sharing) +### User Manual Document +- 📃 [User Manual](https://docs.google.com/document/d/1npM7LlKqEH4eLSaIJUsVhWk6_DC4qCrBcZCBaxCqGWk/edit?usp=sharing) +### Coding Standards Document +- 📃 [Coding Standards](https://docs.google.com/document/d/1Prh1NJkLCubiySVKyEGGlkWgBTonqnkokMo-sBYGPYw/edit?usp=sharing) +### Architectural Requirements Document +- 📃 [Architectural Requirements](https://docs.google.com/document/d/1GADUq8VWsgqLFTfSPIBHwsFnrli8AbZGp7uwuRqVZu8/edit?usp=sharing) +### Project Board +- 📋 [Project Board](https://github.com/orgs/COS301-SE-2023/projects/38) ## Individuals @@ -82,8 +68,8 @@ implementing them. To improve in this area, Theo is dedicating time to relevant and learning resources Links: -- https://www.linkedin.com/in/theodor-le-roux-123a4a274 -- https://github.com/theodorleroux +- [Linkedin](https://www.linkedin.com/in/theodor-le-roux-123a4a274) +- [Github](https://github.com/theodorleroux) ### Ethan Ethan is a proficient team player, adept at completing tasks swiftly and effectively. He has @@ -104,8 +90,8 @@ committed to integrating these tests at every stage of development, thereby stre his skill set in this area. Links: -- https://www.linkedin.com/in/ethan-de-beer-257403277 -- https://github.com/SkulderLock +- [Linkedin](https://www.linkedin.com/in/ethan-de-beer-257403277) +- [Github](https://github.com/SkulderLock) ### Wian Wian is a versatile and creative problem solver, able to effectively contribute to a wide @@ -124,8 +110,8 @@ for growth. By recognizing this tendency, he can continue to refine his approach problem-solving and project management Links: -- https://github.com/gryffindor-coder -- https://www.linkedin.com/in/wian-du-toit-995238271 +- [Linkedin](https://www.linkedin.com/in/wian-du-toit-995238271) +- [Github](https://github.com/gryffindor-coder) ### Franko Franko is an intrigued and determined engineer who finds solutions to counter-intuitive @@ -150,8 +136,8 @@ and driven, we provide him with clear communication and engaging tasks. This app ensures that he stays focused and delivers exceptional results for the project Links: -- https://www.linkedin.com/in/franko-swanepoel-1071b3277/ -- https://github.com/Krygsmancode +- [Linkedin](https://www.linkedin.com/in/franko-swanepoel-1071b3277/) +- [Github](https://github.com/Krygsmancode) ### Amicke Amicke has been actively involved in project designing and web development. Over time, @@ -175,4 +161,5 @@ working to overcome these shortcomings and constantly seeking opportunities to l and grow as a software developer Links: -- https://github.com/AmickeC +- [Github](https://github.com/AmickeC) +- [Linkedin](https://www.linkedin.com/in/amicke-croucamp-3ab400277/) diff --git a/tsconfig.json b/tsconfig.json index 6d869b48..81eb12f5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,8 @@ { "compileOnSave": false, "compilerOptions": { + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, "baseUrl": "./", "outDir": "./dist/out-tsc", "forceConsistentCasingInFileNames": true,