diff --git a/.framework/node/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json similarity index 100% rename from .framework/node/.devcontainer/devcontainer.json rename to .devcontainer/devcontainer.json diff --git a/.framework/java/.devcontainer/devcontainer.json b/.framework/java/.devcontainer/devcontainer.json deleted file mode 100644 index 5e6dee5..0000000 --- a/.framework/java/.devcontainer/devcontainer.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Anythink Development Container", - "image": "public.ecr.aws/v0a2l7y2/wilco/anythink-devcontainer-java:latest" -} diff --git a/.framework/java/backend/.gitignore b/.framework/java/backend/.gitignore deleted file mode 100644 index dfcbb12..0000000 --- a/.framework/java/backend/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -.gradle/ -/build/ -!gradle/wrapper/gradle-wrapper.jar -*.db - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -nbproject/private/ -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ diff --git a/.framework/java/backend/Dockerfile b/.framework/java/backend/Dockerfile deleted file mode 100644 index 30bdf80..0000000 --- a/.framework/java/backend/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM public.ecr.aws/v0a2l7y2/wilco/anythink-backend-java:latest - diff --git a/.framework/java/backend/Dockerfile.aws b/.framework/java/backend/Dockerfile.aws deleted file mode 100644 index e15ec67..0000000 --- a/.framework/java/backend/Dockerfile.aws +++ /dev/null @@ -1,9 +0,0 @@ -FROM openjdk:21 - -WORKDIR /usr/src -COPY backend ./backend -COPY .wilco ./.wilco - -# Pre-install packages -WORKDIR /usr/src/backend -RUN ./gradlew build diff --git a/.framework/java/backend/LICENSE b/.framework/java/backend/LICENSE deleted file mode 100644 index a6fd2b7..0000000 --- a/.framework/java/backend/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Aisensiy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/.framework/java/backend/README.md b/.framework/java/backend/README.md deleted file mode 100644 index 52e4265..0000000 --- a/.framework/java/backend/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Anythink Market Backend - -# How it works - -The application uses Spring Boot (Web, Mybatis). - -And the code is organized as this: - -1. `api` is the web layer implemented by Spring MVC -2. `core` is the business model including entities and services -3. `application` is the high-level services for querying the data transfer objects -4. `infrastructure` contains all the implementation classes as the technique details - -# Getting started - -You'll need Java 21 installed. - - ./gradlew bootRun - -To test that it works, open a browser tab at http://localhost:3000/api/tags -Alternatively, you can run: - - curl http://localhost:3000/api/tags - -# Run test - -The repository contains a lot of test cases to cover both api test and repository test. - - ./gradlew test - -# Code format - -Use spotless for code format. - - ./gradlew spotlessJavaApply diff --git a/.framework/java/backend/build.gradle b/.framework/java/backend/build.gradle deleted file mode 100644 index 2f04f67..0000000 --- a/.framework/java/backend/build.gradle +++ /dev/null @@ -1,79 +0,0 @@ -plugins { - id 'org.springframework.boot' version '3.2.2' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' - id 'java' - id "com.diffplug.spotless" version "6.25.0" -} - -version = '0.0.1-SNAPSHOT' -sourceCompatibility = '21' -targetCompatibility = '21' - -spotless { - java { - target project.fileTree(project.rootDir) { - include '**/*.java' - exclude 'build/generated/**/*.*', 'build/generated-examples/**/*.*' - } - googleJavaFormat() - } -} - -repositories { - mavenCentral() -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } -} - -tasks.named("spotlessJava").configure { dependsOn("processResources") } -tasks.named("spotlessJava").configure { dependsOn("compileJava") } -tasks.named("spotlessJava").configure { dependsOn("compileTestJava") } -spotlessJava.dependsOn test - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'jakarta.validation:jakarta.validation-api:3.0.2' - implementation 'org.springframework.boot:spring-boot-starter-hateoas' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'org.springframework.boot:spring-boot-devtools' - implementation 'org.springframework.security:spring-security-web' - implementation 'org.springframework.security:spring-security-config' - implementation 'com.squareup.okhttp3:okhttp:4.9.1' - implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3' - implementation 'org.flywaydb:flyway-core' - implementation 'io.jsonwebtoken:jjwt-api:0.11.2' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2', - 'io.jsonwebtoken:jjwt-jackson:0.11.2' - implementation 'joda-time:joda-time:2.10.13' - implementation 'org.xerial:sqlite-jdbc:3.36.0.3' - implementation 'org.postgresql:postgresql:42.2.24' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.1' - - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - - testImplementation 'io.rest-assured:rest-assured:5.4.0' - testImplementation 'io.rest-assured:json-path:5.4.0' - testImplementation 'io.rest-assured:xml-path:5.4.0' - testImplementation 'io.rest-assured:spring-mock-mvc:5.4.0' - testImplementation 'org.springframework.security:spring-security-test' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3' - testImplementation 'com.h2database:h2:1.4.200' -} - -tasks.named('test') { - useJUnitPlatform() -} - -tasks.named('clean') { - doFirst { - delete './dev.db' - } -} diff --git a/.framework/java/backend/gradle/wrapper/gradle-wrapper.jar b/.framework/java/backend/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c..0000000 Binary files a/.framework/java/backend/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/.framework/java/backend/gradle/wrapper/gradle-wrapper.properties b/.framework/java/backend/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a595206..0000000 --- a/.framework/java/backend/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/.framework/java/backend/gradlew b/.framework/java/backend/gradlew deleted file mode 100755 index 4f906e0..0000000 --- a/.framework/java/backend/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/.framework/java/backend/gradlew.bat b/.framework/java/backend/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/.framework/java/backend/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/.framework/java/backend/src/main/java/io/spring/AnythinkMarketApplication.java b/.framework/java/backend/src/main/java/io/spring/AnythinkMarketApplication.java deleted file mode 100644 index 8469390..0000000 --- a/.framework/java/backend/src/main/java/io/spring/AnythinkMarketApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.spring; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class AnythinkMarketApplication { - - public static void main(String[] args) { - SpringApplication.run(AnythinkMarketApplication.class, args); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/JacksonCustomizations.java b/.framework/java/backend/src/main/java/io/spring/JacksonCustomizations.java deleted file mode 100644 index 874a46e..0000000 --- a/.framework/java/backend/src/main/java/io/spring/JacksonCustomizations.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.spring; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.Module; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import java.io.IOException; -import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class JacksonCustomizations { - - @Bean - public Module anythinkMarkerModules() { - return new AnythinkMarketModules(); - } - - public static class AnythinkMarketModules extends SimpleModule { - public AnythinkMarketModules() { - addSerializer(DateTime.class, new DateTimeSerializer()); - } - } - - public static class DateTimeSerializer extends StdSerializer { - - protected DateTimeSerializer() { - super(DateTime.class); - } - - @Override - public void serialize(DateTime value, JsonGenerator gen, SerializerProvider provider) - throws IOException { - if (value == null) { - gen.writeNull(); - } else { - gen.writeString(ISODateTimeFormat.dateTime().withZoneUTC().print(value)); - } - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/MyBatisConfig.java b/.framework/java/backend/src/main/java/io/spring/MyBatisConfig.java deleted file mode 100644 index d1f741c..0000000 --- a/.framework/java/backend/src/main/java/io/spring/MyBatisConfig.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.spring; - -import org.springframework.context.annotation.Configuration; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@Configuration -@EnableTransactionManagement -public class MyBatisConfig {} diff --git a/.framework/java/backend/src/main/java/io/spring/Util.java b/.framework/java/backend/src/main/java/io/spring/Util.java deleted file mode 100644 index d2512ac..0000000 --- a/.framework/java/backend/src/main/java/io/spring/Util.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.spring; - -public class Util { - public static boolean isEmpty(String value) { - return value == null || value.isEmpty(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/CommentsApi.java b/.framework/java/backend/src/main/java/io/spring/api/CommentsApi.java deleted file mode 100644 index 63e4a0a..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/CommentsApi.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.spring.api; - -import com.fasterxml.jackson.annotation.JsonRootName; -import io.spring.api.exception.ResourceNotFoundException; -import io.spring.application.CommentQueryService; -import io.spring.application.data.CommentData; -import io.spring.core.comment.Comment; -import io.spring.core.comment.CommentRepository; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.User; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotBlank; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "/api/items/{slug}/comments") -@AllArgsConstructor -public class CommentsApi { - private ItemRepository itemRepository; - private CommentRepository commentRepository; - private CommentQueryService commentQueryService; - - @PostMapping - public ResponseEntity createComment( - @PathVariable("slug") String slug, - @AuthenticationPrincipal User user, - @Valid @RequestBody NewCommentParam newCommentParam) { - Item item = itemRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); - Comment comment = new Comment(newCommentParam.getBody(), user.getId(), item.getId()); - commentRepository.save(comment); - return ResponseEntity.status(201) - .body(commentResponse(commentQueryService.findById(comment.getId(), user).get())); - } - - @GetMapping - public ResponseEntity getComments( - @PathVariable("slug") String slug, @AuthenticationPrincipal User user) { - Item item = itemRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); - List comments = commentQueryService.findByItemId(item.getId(), user); - return ResponseEntity.ok( - new HashMap() { - { - put("comments", comments); - } - }); - } - - @RequestMapping(path = "{id}", method = RequestMethod.DELETE) - public ResponseEntity deleteComment( - @PathVariable("slug") String slug, - @PathVariable("id") String commentId, - @AuthenticationPrincipal User user) { - Item item = itemRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); - return commentRepository - .findById(item.getId(), commentId) - .map( - comment -> { - commentRepository.remove(comment); - return ResponseEntity.noContent().build(); - }) - .orElseThrow(ResourceNotFoundException::new); - } - - private Map commentResponse(CommentData commentData) { - return new HashMap() { - { - put("comment", commentData); - } - }; - } -} - -@Getter -@NoArgsConstructor -@JsonRootName("comment") -class NewCommentParam { - @NotBlank(message = "can't be empty") - private String body; -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/CurrentUserApi.java b/.framework/java/backend/src/main/java/io/spring/api/CurrentUserApi.java deleted file mode 100644 index 07f9dc9..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/CurrentUserApi.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.spring.api; - -import io.spring.application.UserQueryService; -import io.spring.application.data.UserData; -import io.spring.application.data.UserWithToken; -import io.spring.application.user.UpdateUserCommand; -import io.spring.application.user.UpdateUserParam; -import io.spring.application.user.UserService; -import io.spring.core.user.User; -import jakarta.validation.Valid; -import java.util.HashMap; -import java.util.Map; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "/api/user") -@AllArgsConstructor -public class CurrentUserApi { - - private UserQueryService userQueryService; - private UserService userService; - - @GetMapping - public ResponseEntity currentUser( - @AuthenticationPrincipal User currentUser, - @RequestHeader(value = "Authorization") String authorization) { - UserData userData = userQueryService.findById(currentUser.getId()).get(); - return ResponseEntity.ok( - userResponse(new UserWithToken(userData, authorization.split(" ")[1]))); - } - - @PutMapping - public ResponseEntity updateProfile( - @AuthenticationPrincipal User currentUser, - @RequestHeader("Authorization") String token, - @Valid @RequestBody UpdateUserParam updateUserParam) { - - userService.updateUser(new UpdateUserCommand(currentUser, updateUserParam)); - UserData userData = userQueryService.findById(currentUser.getId()).get(); - return ResponseEntity.ok(userResponse(new UserWithToken(userData, token.split(" ")[1]))); - } - - private Map userResponse(UserWithToken userWithToken) { - return new HashMap() { - { - put("user", userWithToken); - } - }; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/ItemApi.java b/.framework/java/backend/src/main/java/io/spring/api/ItemApi.java deleted file mode 100644 index 6384db4..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/ItemApi.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.spring.api; - -import io.spring.api.exception.NoAuthorizationException; -import io.spring.api.exception.ResourceNotFoundException; -import io.spring.application.ItemQueryService; -import io.spring.application.data.ItemData; -import io.spring.application.item.ItemCommandService; -import io.spring.application.item.UpdateItemParam; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.service.AuthorizationService; -import io.spring.core.user.User; -import jakarta.validation.Valid; -import java.util.HashMap; -import java.util.Map; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "/api/items/{slug}") -@AllArgsConstructor -public class ItemApi { - private ItemQueryService itemQueryService; - private ItemRepository itemRepository; - private ItemCommandService itemCommandService; - - @GetMapping - public ResponseEntity item( - @PathVariable("slug") String slug, @AuthenticationPrincipal User user) { - return itemQueryService - .findBySlug(slug, user) - .map(itemData -> ResponseEntity.ok(itemResponse(itemData))) - .orElseThrow(ResourceNotFoundException::new); - } - - @PutMapping - public ResponseEntity updateItem( - @PathVariable("slug") String slug, - @AuthenticationPrincipal User user, - @Valid @RequestBody UpdateItemParam updateItemParam) { - return itemRepository - .findBySlug(slug) - .map( - item -> { - if (!AuthorizationService.canWriteItem(user, item)) { - throw new NoAuthorizationException(); - } - Item updatedItem = itemCommandService.updateItem(item, updateItemParam); - return ResponseEntity.ok( - itemResponse(itemQueryService.findBySlug(updatedItem.getSlug(), user).get())); - }) - .orElseThrow(ResourceNotFoundException::new); - } - - @DeleteMapping - public ResponseEntity deleteItem( - @PathVariable("slug") String slug, @AuthenticationPrincipal User user) { - return itemRepository - .findBySlug(slug) - .map( - item -> { - if (!AuthorizationService.canWriteItem(user, item)) { - throw new NoAuthorizationException(); - } - itemRepository.remove(item); - return ResponseEntity.noContent().build(); - }) - .orElseThrow(ResourceNotFoundException::new); - } - - private Map itemResponse(ItemData itemData) { - return new HashMap() { - { - put("item", itemData); - } - }; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/ItemFavoriteApi.java b/.framework/java/backend/src/main/java/io/spring/api/ItemFavoriteApi.java deleted file mode 100644 index 48f7a47..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/ItemFavoriteApi.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.spring.api; - -import io.spring.api.exception.ResourceNotFoundException; -import io.spring.application.ItemQueryService; -import io.spring.application.data.ItemData; -import io.spring.core.favorite.ItemFavorite; -import io.spring.core.favorite.ItemFavoriteRepository; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.User; -import java.util.HashMap; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "/api/items/{slug}/favorite") -@AllArgsConstructor -public class ItemFavoriteApi { - private ItemFavoriteRepository itemFavoriteRepository; - private ItemRepository itemRepository; - private ItemQueryService itemQueryService; - - @PostMapping - public ResponseEntity favoriteItem( - @PathVariable("slug") String slug, @AuthenticationPrincipal User user) { - Item item = itemRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); - ItemFavorite itemFavorite = new ItemFavorite(item.getId(), user.getId()); - itemFavoriteRepository.save(itemFavorite); - return responseItemData(itemQueryService.findBySlug(slug, user).get()); - } - - @DeleteMapping - public ResponseEntity unfavoriteItem( - @PathVariable("slug") String slug, @AuthenticationPrincipal User user) { - Item item = itemRepository.findBySlug(slug).orElseThrow(ResourceNotFoundException::new); - itemFavoriteRepository - .find(item.getId(), user.getId()) - .ifPresent( - favorite -> { - itemFavoriteRepository.remove(favorite); - }); - return responseItemData(itemQueryService.findBySlug(slug, user).get()); - } - - private ResponseEntity> responseItemData(final ItemData itemData) { - return ResponseEntity.ok( - new HashMap() { - { - put("item", itemData); - } - }); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/ItemsApi.java b/.framework/java/backend/src/main/java/io/spring/api/ItemsApi.java deleted file mode 100644 index e5fb145..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/ItemsApi.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.spring.api; - -import io.spring.application.ItemQueryService; -import io.spring.application.Page; -import io.spring.application.item.ItemCommandService; -import io.spring.application.item.NewItemParam; -import io.spring.core.item.Item; -import io.spring.core.user.User; -import io.spring.infrastructure.service.SendEventService; -import jakarta.validation.Valid; -import java.util.HashMap; -import java.util.Map; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "/api/items") -@AllArgsConstructor -public class ItemsApi { - private ItemCommandService itemCommandService; - private ItemQueryService itemQueryService; - - @PostMapping - public ResponseEntity createItem( - @Valid @RequestBody NewItemParam newItemParam, @AuthenticationPrincipal User user) { - Item item = itemCommandService.createItem(newItemParam, user); - - SendEventService sendEventService = new SendEventService(); - Map metadata = new HashMap<>(); - metadata.put("item", item.getTitle()); - sendEventService.sendEvent("item_created", metadata); - - return ResponseEntity.ok( - new HashMap() { - { - put("item", itemQueryService.findById(item.getId(), user).get()); - } - }); - } - - @GetMapping(path = "feed") - public ResponseEntity getFeed( - @RequestParam(value = "offset", defaultValue = "0") int offset, - @RequestParam(value = "limit", defaultValue = "20") int limit, - @AuthenticationPrincipal User user) { - return ResponseEntity.ok(itemQueryService.findUserFeed(user, new Page(offset, limit))); - } - - @GetMapping - public ResponseEntity getItems( - @RequestParam(value = "offset", defaultValue = "0") int offset, - @RequestParam(value = "limit", defaultValue = "20") int limit, - @RequestParam(value = "tag", required = false) String tag, - @RequestParam(value = "favorited", required = false) String favoritedBy, - @RequestParam(value = "seller", required = false) String seller, - @AuthenticationPrincipal User user) { - return ResponseEntity.ok( - itemQueryService.findRecentItems(tag, seller, favoritedBy, new Page(offset, limit), user)); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/PingApi.java b/.framework/java/backend/src/main/java/io/spring/api/PingApi.java deleted file mode 100644 index 6883ac6..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/PingApi.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.spring.api; - -import io.spring.infrastructure.service.SendEventService; -import java.util.HashMap; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "api/ping") -@AllArgsConstructor -public class PingApi { - @GetMapping - public ResponseEntity ping() { - SendEventService sendEventService = new SendEventService(); - String response = sendEventService.sendEvent("ping", new HashMap<>()); - return ResponseEntity.ok(response); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/ProfileApi.java b/.framework/java/backend/src/main/java/io/spring/api/ProfileApi.java deleted file mode 100644 index 61429e1..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/ProfileApi.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.spring.api; - -import io.spring.api.exception.ResourceNotFoundException; -import io.spring.application.ProfileQueryService; -import io.spring.application.data.ProfileData; -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import java.util.HashMap; -import java.util.Optional; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "api/profiles/{username}") -@AllArgsConstructor -public class ProfileApi { - private ProfileQueryService profileQueryService; - private UserRepository userRepository; - - @GetMapping - public ResponseEntity getProfile( - @PathVariable("username") String username, @AuthenticationPrincipal User user) { - return profileQueryService - .findByUsername(username, user) - .map(this::profileResponse) - .orElseThrow(ResourceNotFoundException::new); - } - - @PostMapping(path = "follow") - public ResponseEntity follow( - @PathVariable("username") String username, @AuthenticationPrincipal User user) { - return userRepository - .findByUsername(username) - .map( - target -> { - FollowRelation followRelation = new FollowRelation(user.getId(), target.getId()); - userRepository.saveRelation(followRelation); - return profileResponse(profileQueryService.findByUsername(username, user).get()); - }) - .orElseThrow(ResourceNotFoundException::new); - } - - @DeleteMapping(path = "follow") - public ResponseEntity unfollow( - @PathVariable("username") String username, @AuthenticationPrincipal User user) { - Optional userOptional = userRepository.findByUsername(username); - if (userOptional.isPresent()) { - User target = userOptional.get(); - return userRepository - .findRelation(user.getId(), target.getId()) - .map( - relation -> { - userRepository.removeRelation(relation); - return profileResponse(profileQueryService.findByUsername(username, user).get()); - }) - .orElseThrow(ResourceNotFoundException::new); - } else { - throw new ResourceNotFoundException(); - } - } - - private ResponseEntity profileResponse(ProfileData profile) { - return ResponseEntity.ok( - new HashMap() { - { - put("profile", profile); - } - }); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/TagsApi.java b/.framework/java/backend/src/main/java/io/spring/api/TagsApi.java deleted file mode 100644 index 9720f37..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/TagsApi.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.spring.api; - -import io.spring.application.TagsQueryService; -import java.util.HashMap; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping(path = "api/tags") -@AllArgsConstructor -public class TagsApi { - private TagsQueryService tagsQueryService; - - @GetMapping - public ResponseEntity getTags() { - return ResponseEntity.ok( - new HashMap() { - { - put("tags", tagsQueryService.allTags()); - } - }); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/UsersApi.java b/.framework/java/backend/src/main/java/io/spring/api/UsersApi.java deleted file mode 100644 index 07f2771..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/UsersApi.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.spring.api; - -import static org.springframework.web.bind.annotation.RequestMethod.POST; - -import com.fasterxml.jackson.annotation.JsonRootName; -import io.spring.api.exception.InvalidAuthenticationException; -import io.spring.application.UserQueryService; -import io.spring.application.data.UserData; -import io.spring.application.data.UserWithToken; -import io.spring.application.user.RegisterParam; -import io.spring.application.user.UserService; -import io.spring.core.service.JwtService; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.service.SendEventService; -import jakarta.validation.Valid; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotBlank; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@AllArgsConstructor -public class UsersApi { - private UserRepository userRepository; - private UserQueryService userQueryService; - private PasswordEncoder passwordEncoder; - private JwtService jwtService; - private UserService userService; - - @RequestMapping(path = "/api/users", method = POST) - public ResponseEntity createUser(@Valid @RequestBody RegisterParam registerParam) { - User user = userService.createUser(registerParam); - - SendEventService sendEventService = new SendEventService(); - Map metadata = new HashMap<>(); - metadata.put("username", user.getUsername()); - sendEventService.sendEvent("user_created", metadata); - - UserData userData = userQueryService.findById(user.getId()).get(); - return ResponseEntity.status(201) - .body(userResponse(new UserWithToken(userData, jwtService.toToken(user)))); - } - - @RequestMapping(path = "/api/users/login", method = POST) - public ResponseEntity userLogin(@Valid @RequestBody LoginParam loginParam) { - Optional optional = userRepository.findByEmail(loginParam.getEmail()); - if (optional.isPresent() - && passwordEncoder.matches(loginParam.getPassword(), optional.get().getPassword())) { - UserData userData = userQueryService.findById(optional.get().getId()).get(); - return ResponseEntity.ok( - userResponse(new UserWithToken(userData, jwtService.toToken(optional.get())))); - } else { - throw new InvalidAuthenticationException(); - } - } - - private Map userResponse(UserWithToken userWithToken) { - return new HashMap() { - { - put("user", userWithToken); - } - }; - } -} - -@Getter -@JsonRootName("user") -@NoArgsConstructor -class LoginParam { - @NotBlank(message = "can't be empty") - @Email(message = "should be an email") - private String email; - - @NotBlank(message = "can't be empty") - private String password; -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/CustomizeExceptionHandler.java b/.framework/java/backend/src/main/java/io/spring/api/exception/CustomizeExceptionHandler.java deleted file mode 100644 index 3e7c5c9..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/CustomizeExceptionHandler.java +++ /dev/null @@ -1,109 +0,0 @@ -package io.spring.api.exception; - -import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; - -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Collectors; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -@RestControllerAdvice -public class CustomizeExceptionHandler extends ResponseEntityExceptionHandler { - - @ExceptionHandler({InvalidRequestException.class}) - public ResponseEntity handleInvalidRequest(RuntimeException e, WebRequest request) { - InvalidRequestException ire = (InvalidRequestException) e; - - List errorResources = - ire.getErrors().getFieldErrors().stream() - .map( - fieldError -> - new FieldErrorResource( - fieldError.getObjectName(), - fieldError.getField(), - fieldError.getCode(), - fieldError.getDefaultMessage())) - .collect(Collectors.toList()); - - ErrorResource error = new ErrorResource(errorResources); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - - return handleExceptionInternal(e, error, headers, UNPROCESSABLE_ENTITY, request); - } - - @ExceptionHandler(InvalidAuthenticationException.class) - public ResponseEntity handleInvalidAuthentication( - InvalidAuthenticationException e, WebRequest request) { - return ResponseEntity.status(UNPROCESSABLE_ENTITY) - .body( - new HashMap() { - { - put("message", e.getMessage()); - } - }); - } - - @Override - protected ResponseEntity handleMethodArgumentNotValid( - MethodArgumentNotValidException e, - HttpHeaders headers, - HttpStatusCode status, - WebRequest request) { - List errorResources = - e.getBindingResult().getFieldErrors().stream() - .map( - fieldError -> - new FieldErrorResource( - fieldError.getObjectName(), - fieldError.getField(), - fieldError.getCode(), - fieldError.getDefaultMessage())) - .collect(Collectors.toList()); - - return ResponseEntity.status(UNPROCESSABLE_ENTITY).body(new ErrorResource(errorResources)); - } - - @ExceptionHandler({ConstraintViolationException.class}) - @ResponseStatus(UNPROCESSABLE_ENTITY) - @ResponseBody - public ErrorResource handleConstraintViolation( - ConstraintViolationException ex, WebRequest request) { - List errors = new ArrayList<>(); - for (ConstraintViolation violation : ex.getConstraintViolations()) { - FieldErrorResource fieldErrorResource = - new FieldErrorResource( - violation.getRootBeanClass().getName(), - getParam(violation.getPropertyPath().toString()), - violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(), - violation.getMessage()); - errors.add(fieldErrorResource); - } - - return new ErrorResource(errors); - } - - private String getParam(String s) { - String[] splits = s.split("\\."); - if (splits.length == 1) { - return s; - } else { - return String.join(".", Arrays.copyOfRange(splits, 2, splits.length)); - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/ErrorResource.java b/.framework/java/backend/src/main/java/io/spring/api/exception/ErrorResource.java deleted file mode 100644 index 1c27805..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/ErrorResource.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.spring.api.exception; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonRootName; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.util.List; - -@JsonSerialize(using = ErrorResourceSerializer.class) -@JsonIgnoreProperties(ignoreUnknown = true) -@lombok.Getter -@JsonRootName("errors") -public class ErrorResource { - private List fieldErrors; - - public ErrorResource(List fieldErrorResources) { - this.fieldErrors = fieldErrorResources; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/ErrorResourceSerializer.java b/.framework/java/backend/src/main/java/io/spring/api/exception/ErrorResourceSerializer.java deleted file mode 100644 index 2ce3816..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/ErrorResourceSerializer.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.spring.api.exception; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ErrorResourceSerializer extends JsonSerializer { - @Override - public void serialize(ErrorResource value, JsonGenerator gen, SerializerProvider serializers) - throws IOException, JsonProcessingException { - Map> json = new HashMap<>(); - gen.writeStartObject(); - gen.writeObjectFieldStart("errors"); - for (FieldErrorResource fieldErrorResource : value.getFieldErrors()) { - if (!json.containsKey(fieldErrorResource.getField())) { - json.put(fieldErrorResource.getField(), new ArrayList()); - } - json.get(fieldErrorResource.getField()).add(fieldErrorResource.getMessage()); - } - for (Map.Entry> pair : json.entrySet()) { - gen.writeArrayFieldStart(pair.getKey()); - pair.getValue() - .forEach( - content -> { - try { - gen.writeString(content); - } catch (IOException e) { - e.printStackTrace(); - } - }); - gen.writeEndArray(); - } - gen.writeEndObject(); - gen.writeEndObject(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/FieldErrorResource.java b/.framework/java/backend/src/main/java/io/spring/api/exception/FieldErrorResource.java deleted file mode 100644 index 13d5731..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/FieldErrorResource.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.spring.api.exception; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@JsonIgnoreProperties(ignoreUnknown = true) -@Getter -@AllArgsConstructor -public class FieldErrorResource { - private String resource; - private String field; - private String code; - private String message; -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/InvalidAuthenticationException.java b/.framework/java/backend/src/main/java/io/spring/api/exception/InvalidAuthenticationException.java deleted file mode 100644 index 96af7a8..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/InvalidAuthenticationException.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.spring.api.exception; - -public class InvalidAuthenticationException extends RuntimeException { - - public InvalidAuthenticationException() { - super("invalid email or password"); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/InvalidRequestException.java b/.framework/java/backend/src/main/java/io/spring/api/exception/InvalidRequestException.java deleted file mode 100644 index 68b6c86..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/InvalidRequestException.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.api.exception; - -import org.springframework.validation.Errors; - -@SuppressWarnings("serial") -public class InvalidRequestException extends RuntimeException { - private final Errors errors; - - public InvalidRequestException(Errors errors) { - super(""); - this.errors = errors; - } - - public Errors getErrors() { - return errors; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/NoAuthorizationException.java b/.framework/java/backend/src/main/java/io/spring/api/exception/NoAuthorizationException.java deleted file mode 100644 index 6741423..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/NoAuthorizationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.spring.api.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(HttpStatus.FORBIDDEN) -public class NoAuthorizationException extends RuntimeException {} diff --git a/.framework/java/backend/src/main/java/io/spring/api/exception/ResourceNotFoundException.java b/.framework/java/backend/src/main/java/io/spring/api/exception/ResourceNotFoundException.java deleted file mode 100644 index 8401e52..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/exception/ResourceNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.spring.api.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@ResponseStatus(value = HttpStatus.NOT_FOUND) -public class ResourceNotFoundException extends RuntimeException {} diff --git a/.framework/java/backend/src/main/java/io/spring/api/security/JwtTokenFilter.java b/.framework/java/backend/src/main/java/io/spring/api/security/JwtTokenFilter.java deleted file mode 100644 index b03e9d1..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/security/JwtTokenFilter.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.spring.api.security; - -import io.spring.core.service.JwtService; -import io.spring.core.user.UserRepository; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Collections; -import java.util.Optional; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.web.filter.OncePerRequestFilter; - -@SuppressWarnings("SpringJavaAutowiringInspection") -public class JwtTokenFilter extends OncePerRequestFilter { - @Autowired private UserRepository userRepository; - @Autowired private JwtService jwtService; - private final String header = "Authorization"; - - @Override - protected void doFilterInternal( - HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - getTokenString(request.getHeader(header)) - .flatMap(token -> jwtService.getSubFromToken(token)) - .ifPresent( - id -> { - if (SecurityContextHolder.getContext().getAuthentication() == null) { - userRepository - .findById(id) - .ifPresent( - user -> { - UsernamePasswordAuthenticationToken authenticationToken = - new UsernamePasswordAuthenticationToken( - user, null, Collections.emptyList()); - authenticationToken.setDetails( - new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); - }); - } - }); - - filterChain.doFilter(request, response); - } - - private Optional getTokenString(String header) { - if (header == null) { - return Optional.empty(); - } else { - String[] split = header.split(" "); - if (split.length < 2) { - return Optional.empty(); - } else { - return Optional.ofNullable(split[1]); - } - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/api/security/WebSecurityConfig.java b/.framework/java/backend/src/main/java/io/spring/api/security/WebSecurityConfig.java deleted file mode 100644 index 9523e96..0000000 --- a/.framework/java/backend/src/main/java/io/spring/api/security/WebSecurityConfig.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.spring.api.security; - -import java.util.Arrays; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.HttpStatusEntryPoint; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -@Configuration -@EnableWebSecurity -public class WebSecurityConfig { - - @Bean - public JwtTokenFilter jwtTokenFilter() { - return new JwtTokenFilter(); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf(csrf -> csrf.disable()) - .cors((cors) -> cors.configurationSource(corsConfigurationSource())) - .sessionManagement( - (session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .exceptionHandling( - exceptionHandling -> - exceptionHandling.authenticationEntryPoint( - new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))) - .authorizeHttpRequests( - auth -> - auth.requestMatchers(HttpMethod.OPTIONS, "/**") - .permitAll() - .requestMatchers("/actuator/**") - .permitAll() - .requestMatchers("/error") - .permitAll() - .requestMatchers("/health") - .permitAll() - .requestMatchers("/api/ping") - .permitAll() - .requestMatchers(HttpMethod.GET, "/api/items/feed") - .authenticated() - .requestMatchers(HttpMethod.POST, "/api/users", "/api/users/login") - .permitAll() - .requestMatchers( - HttpMethod.GET, "/api/items/**", "/api/profiles/**", "/api/tags") - .permitAll() - .anyRequest() - .authenticated()); - - http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class); - return http.build(); - } - - @Bean - CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(Arrays.asList("*")); - configuration.setAllowedMethods(Arrays.asList("*")); - configuration.setAllowedHeaders(Arrays.asList("*")); - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", configuration); - return source; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/CommentQueryService.java b/.framework/java/backend/src/main/java/io/spring/application/CommentQueryService.java deleted file mode 100644 index dfba6ef..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/CommentQueryService.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.spring.application; - -import io.spring.application.data.CommentData; -import io.spring.core.user.User; -import io.spring.infrastructure.mybatis.readservice.CommentReadService; -import io.spring.infrastructure.mybatis.readservice.UserRelationshipQueryService; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.AllArgsConstructor; -import org.joda.time.DateTime; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -public class CommentQueryService { - private CommentReadService commentReadService; - private UserRelationshipQueryService userRelationshipQueryService; - - public Optional findById(String id, User user) { - CommentData commentData = commentReadService.findById(id); - if (commentData == null) { - return Optional.empty(); - } else { - commentData - .getProfileData() - .setFollowing( - userRelationshipQueryService.isUserFollowing( - user.getId(), commentData.getProfileData().getId())); - } - return Optional.ofNullable(commentData); - } - - public List findByItemId(String itemId, User user) { - List comments = commentReadService.findByItemId(itemId); - if (comments.size() > 0 && user != null) { - Set followingSellers = - userRelationshipQueryService.followingSellers( - user.getId(), - comments.stream() - .map(commentData -> commentData.getProfileData().getId()) - .collect(Collectors.toList())); - comments.forEach( - commentData -> { - if (followingSellers.contains(commentData.getProfileData().getId())) { - commentData.getProfileData().setFollowing(true); - } - }); - } - return comments; - } - - public CursorPager findByItemIdWithCursor( - String itemId, User user, CursorPageParameter page) { - List comments = commentReadService.findByItemIdWithCursor(itemId, page); - if (comments.isEmpty()) { - return new CursorPager<>(new ArrayList<>(), page.getDirection(), false); - } - if (user != null) { - Set followingSellers = - userRelationshipQueryService.followingSellers( - user.getId(), - comments.stream() - .map(commentData -> commentData.getProfileData().getId()) - .collect(Collectors.toList())); - comments.forEach( - commentData -> { - if (followingSellers.contains(commentData.getProfileData().getId())) { - commentData.getProfileData().setFollowing(true); - } - }); - } - boolean hasExtra = comments.size() > page.getLimit(); - if (hasExtra) { - comments.remove(page.getLimit()); - } - if (!page.isNext()) { - Collections.reverse(comments); - } - return new CursorPager<>(comments, page.getDirection(), hasExtra); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/CursorPageParameter.java b/.framework/java/backend/src/main/java/io/spring/application/CursorPageParameter.java deleted file mode 100644 index 1953137..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/CursorPageParameter.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.spring.application; - -import io.spring.application.CursorPager.Direction; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class CursorPageParameter { - private static final int MAX_LIMIT = 1000; - private int limit = 20; - private T cursor; - private Direction direction; - - public CursorPageParameter(T cursor, int limit, Direction direction) { - setLimit(limit); - setCursor(cursor); - setDirection(direction); - } - - public boolean isNext() { - return direction == Direction.NEXT; - } - - public int getQueryLimit() { - return limit + 1; - } - - private void setCursor(T cursor) { - this.cursor = cursor; - } - - private void setLimit(int limit) { - if (limit > MAX_LIMIT) { - this.limit = MAX_LIMIT; - } else if (limit > 0) { - this.limit = limit; - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/CursorPager.java b/.framework/java/backend/src/main/java/io/spring/application/CursorPager.java deleted file mode 100644 index 13d55d4..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/CursorPager.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.spring.application; - -import java.util.List; -import lombok.Getter; - -@Getter -public class CursorPager { - private List data; - private boolean next; - private boolean previous; - - public CursorPager(List data, Direction direction, boolean hasExtra) { - this.data = data; - - if (direction == Direction.NEXT) { - this.previous = false; - this.next = hasExtra; - } else { - this.next = false; - this.previous = hasExtra; - } - } - - public boolean hasNext() { - return next; - } - - public boolean hasPrevious() { - return previous; - } - - public PageCursor getStartCursor() { - return data.isEmpty() ? null : data.get(0).getCursor(); - } - - public PageCursor getEndCursor() { - return data.isEmpty() ? null : data.get(data.size() - 1).getCursor(); - } - - public enum Direction { - PREV, - NEXT - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/DateTimeCursor.java b/.framework/java/backend/src/main/java/io/spring/application/DateTimeCursor.java deleted file mode 100644 index cfcc86b..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/DateTimeCursor.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.spring.application; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; - -public class DateTimeCursor extends PageCursor { - - public DateTimeCursor(DateTime data) { - super(data); - } - - @Override - public String toString() { - return String.valueOf(getData().getMillis()); - } - - public static DateTime parse(String cursor) { - if (cursor == null) { - return null; - } - return new DateTime().withMillis(Long.parseLong(cursor)).withZone(DateTimeZone.UTC); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/ItemQueryService.java b/.framework/java/backend/src/main/java/io/spring/application/ItemQueryService.java deleted file mode 100644 index d78a366..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/ItemQueryService.java +++ /dev/null @@ -1,185 +0,0 @@ -package io.spring.application; - -import static java.util.stream.Collectors.toList; - -import io.spring.application.data.ItemData; -import io.spring.application.data.ItemDataList; -import io.spring.application.data.ItemFavoriteCount; -import io.spring.core.user.User; -import io.spring.infrastructure.mybatis.readservice.ItemFavoritesReadService; -import io.spring.infrastructure.mybatis.readservice.ItemReadService; -import io.spring.infrastructure.mybatis.readservice.UserRelationshipQueryService; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import lombok.AllArgsConstructor; -import org.joda.time.DateTime; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -public class ItemQueryService { - private ItemReadService itemReadService; - private UserRelationshipQueryService userRelationshipQueryService; - private ItemFavoritesReadService itemFavoritesReadService; - - public Optional findById(String id, User user) { - ItemData itemData = itemReadService.findById(id); - if (itemData == null) { - return Optional.empty(); - } else { - if (user != null) { - fillExtraInfo(id, user, itemData); - } - return Optional.of(itemData); - } - } - - public Optional findBySlug(String slug, User user) { - ItemData itemData = itemReadService.findBySlug(slug); - if (itemData == null) { - return Optional.empty(); - } else { - if (user != null) { - fillExtraInfo(itemData.getId(), user, itemData); - } - - setFavoriteCount(Collections.singletonList(itemData)); - return Optional.of(itemData); - } - } - - public CursorPager findRecentItemsWithCursor( - String tag, - String seller, - String favoritedBy, - CursorPageParameter page, - User currentUser) { - List itemIds = itemReadService.findItemsWithCursor(tag, seller, favoritedBy, page); - if (itemIds.size() == 0) { - return new CursorPager<>(new ArrayList<>(), page.getDirection(), false); - } else { - boolean hasExtra = itemIds.size() > page.getLimit(); - if (hasExtra) { - itemIds.remove(page.getLimit()); - } - if (!page.isNext()) { - Collections.reverse(itemIds); - } - - List items = itemReadService.findItems(itemIds); - fillExtraInfo(items, currentUser); - - return new CursorPager<>(items, page.getDirection(), hasExtra); - } - } - - public CursorPager findUserFeedWithCursor( - User user, CursorPageParameter page) { - List followedUsers = userRelationshipQueryService.followedUsers(user.getId()); - if (followedUsers.size() == 0) { - return new CursorPager<>(new ArrayList<>(), page.getDirection(), false); - } else { - List items = itemReadService.findItemsOfSellersWithCursor(followedUsers, page); - boolean hasExtra = items.size() > page.getLimit(); - if (hasExtra) { - items.remove(page.getLimit()); - } - if (!page.isNext()) { - Collections.reverse(items); - } - fillExtraInfo(items, user); - return new CursorPager<>(items, page.getDirection(), hasExtra); - } - } - - public ItemDataList findRecentItems( - String tag, String seller, String favoritedBy, Page page, User currentUser) { - List itemIds = itemReadService.queryItems(tag, seller, favoritedBy, page); - int itemCount = itemReadService.countItem(tag, seller, favoritedBy); - if (itemIds.size() == 0) { - return new ItemDataList(new ArrayList<>(), itemCount); - } else { - List items = itemReadService.findItems(itemIds); - fillExtraInfo(items, currentUser); - return new ItemDataList(items, itemCount); - } - } - - public ItemDataList findUserFeed(User user, Page page) { - List followedUsers = userRelationshipQueryService.followedUsers(user.getId()); - if (followedUsers.size() == 0) { - return new ItemDataList(new ArrayList<>(), 0); - } else { - List items = itemReadService.findItemsOfSellers(followedUsers, page); - int offset = page.getOffset(); - int limit = page.getLimit(); - int endIndex = Math.min(offset + limit, items.size()); - items = items.subList(offset, endIndex); - - fillExtraInfo(items, user); - int count = itemReadService.countFeedSize(followedUsers); - return new ItemDataList(items, count); - } - } - - private void fillExtraInfo(List items, User currentUser) { - setFavoriteCount(items); - if (currentUser != null) { - setIsFavorite(items, currentUser); - setIsFollowingSeller(items, currentUser); - } - } - - private void setIsFollowingSeller(List items, User currentUser) { - Set followingSellers = - userRelationshipQueryService.followingSellers( - currentUser.getId(), - items.stream().map(itemData1 -> itemData1.getProfileData().getId()).collect(toList())); - items.forEach( - itemData -> { - if (followingSellers.contains(itemData.getProfileData().getId())) { - itemData.getProfileData().setFollowing(true); - } - }); - } - - private void setFavoriteCount(List items) { - List favoritesCounts = - itemFavoritesReadService.itemsFavoriteCount( - items.stream().map(ItemData::getId).collect(toList())); - Map countMap = new HashMap<>(); - favoritesCounts.forEach( - item -> { - countMap.put(item.getId(), item.getCount()); - }); - items.forEach(itemData -> itemData.setFavoritesCount(countMap.get(itemData.getId()))); - } - - private void setIsFavorite(List items, User currentUser) { - Set favoritedItems = - itemFavoritesReadService.userFavorites( - items.stream().map(itemData -> itemData.getId()).collect(toList()), currentUser); - - items.forEach( - itemData -> { - if (favoritedItems.contains(itemData.getId())) { - itemData.setFavorited(true); - } - }); - } - - private void fillExtraInfo(String id, User user, ItemData itemData) { - itemData.setFavorited(itemFavoritesReadService.isUserFavorite(user.getId(), id)); - itemData.setFavoritesCount(itemFavoritesReadService.itemFavoriteCount(id)); - itemData - .getProfileData() - .setFollowing( - userRelationshipQueryService.isUserFollowing( - user.getId(), itemData.getProfileData().getId())); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/Node.java b/.framework/java/backend/src/main/java/io/spring/application/Node.java deleted file mode 100644 index e4ccac8..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/Node.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.spring.application; - -public interface Node { - PageCursor getCursor(); -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/Page.java b/.framework/java/backend/src/main/java/io/spring/application/Page.java deleted file mode 100644 index d273e99..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/Page.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.spring.application; - -import lombok.Data; -import lombok.NoArgsConstructor; - -@NoArgsConstructor -@Data -public class Page { - private static final int MAX_LIMIT = 100; - private int offset = 0; - private int limit = 20; - - public Page(int offset, int limit) { - setOffset(offset); - setLimit(limit); - } - - private void setOffset(int offset) { - if (offset > 0) { - this.offset = offset; - } - } - - private void setLimit(int limit) { - if (limit > MAX_LIMIT) { - this.limit = MAX_LIMIT; - } else if (limit > 0) { - this.limit = limit; - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/PageCursor.java b/.framework/java/backend/src/main/java/io/spring/application/PageCursor.java deleted file mode 100644 index 0279f3b..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/PageCursor.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.spring.application; - -public abstract class PageCursor { - private T data; - - public PageCursor(T data) { - this.data = data; - } - - public T getData() { - return data; - } - - @Override - public String toString() { - return data.toString(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/ProfileQueryService.java b/.framework/java/backend/src/main/java/io/spring/application/ProfileQueryService.java deleted file mode 100644 index d92542d..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/ProfileQueryService.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.spring.application; - -import io.spring.application.data.ProfileData; -import io.spring.application.data.UserData; -import io.spring.core.user.User; -import io.spring.infrastructure.mybatis.readservice.UserReadService; -import io.spring.infrastructure.mybatis.readservice.UserRelationshipQueryService; -import java.util.Optional; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; - -@Component -@AllArgsConstructor -public class ProfileQueryService { - private UserReadService userReadService; - private UserRelationshipQueryService userRelationshipQueryService; - - public Optional findByUsername(String username, User currentUser) { - UserData userData = userReadService.findByUsername(username); - if (userData == null) { - return Optional.empty(); - } else { - ProfileData profileData = - new ProfileData( - userData.getId(), - userData.getUsername(), - userData.getBio(), - userData.getImage(), - currentUser != null - && userRelationshipQueryService.isUserFollowing( - currentUser.getId(), userData.getId())); - return Optional.of(profileData); - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/TagsQueryService.java b/.framework/java/backend/src/main/java/io/spring/application/TagsQueryService.java deleted file mode 100644 index 12e0790..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/TagsQueryService.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.spring.application; - -import io.spring.infrastructure.mybatis.readservice.TagReadService; -import java.util.List; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -public class TagsQueryService { - private TagReadService tagReadService; - - public List allTags() { - return tagReadService.all(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/UserQueryService.java b/.framework/java/backend/src/main/java/io/spring/application/UserQueryService.java deleted file mode 100644 index f0f901a..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/UserQueryService.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.application; - -import io.spring.application.data.UserData; -import io.spring.infrastructure.mybatis.readservice.UserReadService; -import java.util.Optional; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -public class UserQueryService { - private UserReadService userReadService; - - public Optional findById(String id) { - return Optional.ofNullable(userReadService.findById(id)); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/CommentData.java b/.framework/java/backend/src/main/java/io/spring/application/data/CommentData.java deleted file mode 100644 index a31dbf4..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/CommentData.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.spring.application.data; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.spring.application.DateTimeCursor; -import io.spring.application.Node; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.joda.time.DateTime; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class CommentData implements Node { - private String id; - private String body; - @JsonIgnore private String itemId; - private DateTime createdAt; - private DateTime updatedAt; - - @JsonProperty("seller") - private ProfileData profileData; - - @Override - public DateTimeCursor getCursor() { - return new DateTimeCursor(createdAt); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/ItemData.java b/.framework/java/backend/src/main/java/io/spring/application/data/ItemData.java deleted file mode 100644 index e65f04c..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/ItemData.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.spring.application.data; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.spring.application.DateTimeCursor; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.joda.time.DateTime; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class ItemData implements io.spring.application.Node { - private String id; - private String slug; - private String title; - private String description; - private String image; - private boolean favorited; - private int favoritesCount; - private DateTime createdAt; - private DateTime updatedAt; - private List tagList; - - @JsonProperty("seller") - private ProfileData profileData; - - @Override - public DateTimeCursor getCursor() { - return new DateTimeCursor(updatedAt); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/ItemDataList.java b/.framework/java/backend/src/main/java/io/spring/application/data/ItemDataList.java deleted file mode 100644 index 983d17c..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/ItemDataList.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.spring.application.data; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import lombok.Getter; - -@Getter -public class ItemDataList { - @JsonProperty("items") - private final List itemDatas; - - @JsonProperty("itemsCount") - private final int count; - - public ItemDataList(List itemDatas, int count) { - - this.itemDatas = itemDatas; - this.count = count; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/ItemFavoriteCount.java b/.framework/java/backend/src/main/java/io/spring/application/data/ItemFavoriteCount.java deleted file mode 100644 index 6d875df..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/ItemFavoriteCount.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.spring.application.data; - -import lombok.Value; - -@Value -public class ItemFavoriteCount { - private String id; - private Integer count; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/ProfileData.java b/.framework/java/backend/src/main/java/io/spring/application/data/ProfileData.java deleted file mode 100644 index 82ef5f9..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/ProfileData.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.application.data; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class ProfileData { - @JsonIgnore private String id; - private String username; - private String bio; - private String image; - private boolean following; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/UserData.java b/.framework/java/backend/src/main/java/io/spring/application/data/UserData.java deleted file mode 100644 index c50cc19..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/UserData.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.spring.application.data; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserData { - private String id; - private String email; - private String username; - private String bio; - private String image; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/data/UserWithToken.java b/.framework/java/backend/src/main/java/io/spring/application/data/UserWithToken.java deleted file mode 100644 index eac7f1b..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/data/UserWithToken.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.spring.application.data; - -import lombok.Getter; - -@Getter -public class UserWithToken { - private String email; - private String username; - private String bio; - private String image; - private String token; - - public UserWithToken(UserData userData, String token) { - this.email = userData.getEmail(); - this.username = userData.getUsername(); - this.bio = userData.getBio(); - this.image = userData.getImage(); - this.token = token; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/item/DuplicatedItemConstraint.java b/.framework/java/backend/src/main/java/io/spring/application/item/DuplicatedItemConstraint.java deleted file mode 100644 index 31031a2..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/item/DuplicatedItemConstraint.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.spring.application.item; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Documented -@Constraint(validatedBy = DuplicatedItemValidator.class) -@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE_USE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface DuplicatedItemConstraint { - String message() default "item name exists"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/item/DuplicatedItemValidator.java b/.framework/java/backend/src/main/java/io/spring/application/item/DuplicatedItemValidator.java deleted file mode 100644 index df7326b..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/item/DuplicatedItemValidator.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.application.item; - -import io.spring.application.ItemQueryService; -import io.spring.core.item.Item; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Autowired; - -class DuplicatedItemValidator implements ConstraintValidator { - - @Autowired private ItemQueryService itemQueryService; - - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - return !itemQueryService.findBySlug(Item.toSlug(value), null).isPresent(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/item/ItemCommandService.java b/.framework/java/backend/src/main/java/io/spring/application/item/ItemCommandService.java deleted file mode 100644 index 420c93d..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/item/ItemCommandService.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.spring.application.item; - -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.User; -import jakarta.validation.Valid; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -@Service -@Validated -@AllArgsConstructor -public class ItemCommandService { - - private ItemRepository itemRepository; - - public Item createItem(@Valid NewItemParam newItemParam, User creator) { - Item item = - new Item( - newItemParam.getTitle(), - newItemParam.getDescription(), - newItemParam.getImage(), - newItemParam.getTagList(), - creator.getId()); - itemRepository.save(item); - return item; - } - - public Item updateItem(Item item, @Valid UpdateItemParam updateItemParam) { - item.update( - updateItemParam.getTitle(), updateItemParam.getDescription(), updateItemParam.getImage()); - itemRepository.save(item); - return item; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/item/NewItemParam.java b/.framework/java/backend/src/main/java/io/spring/application/item/NewItemParam.java deleted file mode 100644 index aa1ab9a..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/item/NewItemParam.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.spring.application.item; - -import com.fasterxml.jackson.annotation.JsonRootName; -import jakarta.validation.constraints.NotBlank; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@JsonRootName("item") -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class NewItemParam { - @NotBlank(message = "can't be empty") - @DuplicatedItemConstraint - private String title; - - @NotBlank(message = "can't be empty") - private String description; - - private String image; - - private List tagList; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/item/UpdateItemParam.java b/.framework/java/backend/src/main/java/io/spring/application/item/UpdateItemParam.java deleted file mode 100644 index d2f214e..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/item/UpdateItemParam.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.spring.application.item; - -import com.fasterxml.jackson.annotation.JsonRootName; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -@JsonRootName("item") -public class UpdateItemParam { - private String title = ""; - private String image = ""; - private String description = ""; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedEmailConstraint.java b/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedEmailConstraint.java deleted file mode 100644 index 8e0f3d5..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedEmailConstraint.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.spring.application.user; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Constraint(validatedBy = DuplicatedEmailValidator.class) -@Retention(RetentionPolicy.RUNTIME) -public @interface DuplicatedEmailConstraint { - String message() default "duplicated email"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedEmailValidator.java b/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedEmailValidator.java deleted file mode 100644 index f754397..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedEmailValidator.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.application.user; - -import io.spring.core.user.UserRepository; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Autowired; - -public class DuplicatedEmailValidator - implements ConstraintValidator { - - @Autowired private UserRepository userRepository; - - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - return (value == null || value.isEmpty()) || !userRepository.findByEmail(value).isPresent(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedUsernameConstraint.java b/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedUsernameConstraint.java deleted file mode 100644 index 0e54988..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedUsernameConstraint.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.spring.application.user; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Constraint(validatedBy = DuplicatedUsernameValidator.class) -@Retention(RetentionPolicy.RUNTIME) -@interface DuplicatedUsernameConstraint { - String message() default "duplicated username"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedUsernameValidator.java b/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedUsernameValidator.java deleted file mode 100644 index 4b803bf..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/DuplicatedUsernameValidator.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.application.user; - -import io.spring.core.user.UserRepository; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import org.springframework.beans.factory.annotation.Autowired; - -class DuplicatedUsernameValidator - implements ConstraintValidator { - - @Autowired private UserRepository userRepository; - - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - return (value == null || value.isEmpty()) || !userRepository.findByUsername(value).isPresent(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/RegisterParam.java b/.framework/java/backend/src/main/java/io/spring/application/user/RegisterParam.java deleted file mode 100644 index d629268..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/RegisterParam.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.spring.application.user; - -import com.fasterxml.jackson.annotation.JsonRootName; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotBlank; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@JsonRootName("user") -@AllArgsConstructor -@NoArgsConstructor -public class RegisterParam { - @NotBlank(message = "can't be empty") - @Email(message = "should be an email") - @DuplicatedEmailConstraint - private String email; - - @NotBlank(message = "can't be empty") - @DuplicatedUsernameConstraint - private String username; - - @NotBlank(message = "can't be empty") - private String password; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/UpdateUserCommand.java b/.framework/java/backend/src/main/java/io/spring/application/user/UpdateUserCommand.java deleted file mode 100644 index 9df5230..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/UpdateUserCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.spring.application.user; - -import io.spring.core.user.User; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -@UpdateUserConstraint -public class UpdateUserCommand { - - private User targetUser; - private UpdateUserParam param; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/UpdateUserParam.java b/.framework/java/backend/src/main/java/io/spring/application/user/UpdateUserParam.java deleted file mode 100644 index f0263a0..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/UpdateUserParam.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.spring.application.user; - -import com.fasterxml.jackson.annotation.JsonRootName; -import jakarta.validation.constraints.Email; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@JsonRootName("user") -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class UpdateUserParam { - - @Builder.Default - @Email(message = "should be an email") - private String email = ""; - - @Builder.Default private String password = ""; - @Builder.Default private String username = ""; - @Builder.Default private String bio = ""; - @Builder.Default private String image = ""; -} diff --git a/.framework/java/backend/src/main/java/io/spring/application/user/UserService.java b/.framework/java/backend/src/main/java/io/spring/application/user/UserService.java deleted file mode 100644 index 7772b32..0000000 --- a/.framework/java/backend/src/main/java/io/spring/application/user/UserService.java +++ /dev/null @@ -1,106 +0,0 @@ -package io.spring.application.user; - -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import jakarta.validation.Constraint; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.Valid; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -@Service -@Validated -public class UserService { - private UserRepository userRepository; - private String defaultImage; - private PasswordEncoder passwordEncoder; - - @Autowired - public UserService( - UserRepository userRepository, - @Value("${image.default}") String defaultImage, - PasswordEncoder passwordEncoder) { - this.userRepository = userRepository; - this.defaultImage = defaultImage; - this.passwordEncoder = passwordEncoder; - } - - public User createUser(@Valid RegisterParam registerParam) { - User user = - new User( - registerParam.getEmail(), - registerParam.getUsername(), - passwordEncoder.encode(registerParam.getPassword()), - "", - defaultImage); - userRepository.save(user); - return user; - } - - public void updateUser(@Valid UpdateUserCommand command) { - User user = command.getTargetUser(); - UpdateUserParam updateUserParam = command.getParam(); - user.update( - updateUserParam.getEmail(), - updateUserParam.getUsername(), - updateUserParam.getPassword(), - updateUserParam.getBio(), - updateUserParam.getImage()); - userRepository.save(user); - } -} - -@Constraint(validatedBy = UpdateUserValidator.class) -@Retention(RetentionPolicy.RUNTIME) -@interface UpdateUserConstraint { - - String message() default "invalid update param"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} - -class UpdateUserValidator implements ConstraintValidator { - - @Autowired private UserRepository userRepository; - - @Override - public boolean isValid(UpdateUserCommand value, ConstraintValidatorContext context) { - String inputEmail = value.getParam().getEmail(); - String inputUsername = value.getParam().getUsername(); - final User targetUser = value.getTargetUser(); - - boolean isEmailValid = - userRepository.findByEmail(inputEmail).map(user -> user.equals(targetUser)).orElse(true); - boolean isUsernameValid = - userRepository - .findByUsername(inputUsername) - .map(user -> user.equals(targetUser)) - .orElse(true); - if (isEmailValid && isUsernameValid) { - return true; - } else { - context.disableDefaultConstraintViolation(); - if (!isEmailValid) { - context - .buildConstraintViolationWithTemplate("email already exist") - .addPropertyNode("email") - .addConstraintViolation(); - } - if (!isUsernameValid) { - context - .buildConstraintViolationWithTemplate("username already exist") - .addPropertyNode("username") - .addConstraintViolation(); - } - return false; - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/comment/Comment.java b/.framework/java/backend/src/main/java/io/spring/core/comment/Comment.java deleted file mode 100644 index ecfcfa1..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/comment/Comment.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.spring.core.comment; - -import java.util.UUID; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.joda.time.DateTime; - -@Getter -@NoArgsConstructor -@EqualsAndHashCode(of = "id") -public class Comment { - private String id; - private String body; - private String sellerId; - private String itemId; - private DateTime createdAt; - - public Comment(String body, String sellerId, String itemId) { - this.id = UUID.randomUUID().toString(); - this.body = body; - this.sellerId = sellerId; - this.itemId = itemId; - this.createdAt = new DateTime(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/comment/CommentRepository.java b/.framework/java/backend/src/main/java/io/spring/core/comment/CommentRepository.java deleted file mode 100644 index ad3ab07..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/comment/CommentRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.spring.core.comment; - -import java.util.Optional; - -public interface CommentRepository { - void save(Comment comment); - - Optional findById(String itemId, String id); - - void remove(Comment comment); -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/favorite/ItemFavorite.java b/.framework/java/backend/src/main/java/io/spring/core/favorite/ItemFavorite.java deleted file mode 100644 index 39ce24d..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/favorite/ItemFavorite.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.spring.core.favorite; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class ItemFavorite { - private String itemId; - private String userId; - - public ItemFavorite(String itemId, String userId) { - this.itemId = itemId; - this.userId = userId; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/favorite/ItemFavoriteRepository.java b/.framework/java/backend/src/main/java/io/spring/core/favorite/ItemFavoriteRepository.java deleted file mode 100644 index 61db705..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/favorite/ItemFavoriteRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.spring.core.favorite; - -import java.util.Optional; - -public interface ItemFavoriteRepository { - void save(ItemFavorite itemFavorite); - - Optional find(String itemId, String userId); - - void remove(ItemFavorite favorite); -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/item/Item.java b/.framework/java/backend/src/main/java/io/spring/core/item/Item.java deleted file mode 100644 index 6b39667..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/item/Item.java +++ /dev/null @@ -1,74 +0,0 @@ -package io.spring.core.item; - -import io.spring.Util; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.joda.time.DateTime; - -@Getter -@NoArgsConstructor -@EqualsAndHashCode(of = {"id"}) -public class Item { - private String sellerId; - private String id; - private String slug; - private String title; - private String description; - private String image; - private List tags; - private DateTime createdAt; - private DateTime updatedAt; - - public Item( - String title, String description, String image, List tagList, String sellerId) { - this(title, description, image, tagList, sellerId, new DateTime()); - } - - public Item( - String title, - String description, - String image, - List tagList, - String sellerId, - DateTime createdAt) { - this.id = UUID.randomUUID().toString(); - this.slug = toSlug(title); - this.title = title; - this.description = description; - this.image = image; - this.tags = - Optional.ofNullable(tagList) - .map(list -> new HashSet<>(list).stream().map(Tag::new).collect(Collectors.toList())) - .orElse(new ArrayList()); - - this.sellerId = sellerId; - this.createdAt = createdAt; - this.updatedAt = createdAt; - } - - public void update(String title, String description, String image) { - if (!Util.isEmpty(title)) { - this.title = title; - this.updatedAt = new DateTime(); - } - if (!Util.isEmpty(description)) { - this.description = description; - this.updatedAt = new DateTime(); - } - if (!Util.isEmpty(image)) { - this.image = image; - this.updatedAt = new DateTime(); - } - } - - public static String toSlug(String title) { - return title.toLowerCase().replaceAll("[\\&|[\\uFE30-\\uFFA0]|\\’|\\”|\\s\\?\\,\\.]+", "-"); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/item/ItemRepository.java b/.framework/java/backend/src/main/java/io/spring/core/item/ItemRepository.java deleted file mode 100644 index 6dea2ea..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/item/ItemRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.spring.core.item; - -import java.util.Optional; - -public interface ItemRepository { - - void save(Item item); - - Optional findById(String id); - - Optional findBySlug(String slug); - - void remove(Item item); -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/item/Tag.java b/.framework/java/backend/src/main/java/io/spring/core/item/Tag.java deleted file mode 100644 index 7edd313..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/item/Tag.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.spring.core.item; - -import java.util.UUID; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import org.joda.time.DateTime; - -@NoArgsConstructor -@Data -@EqualsAndHashCode(of = "name") -public class Tag { - private String id; - private String name; - private DateTime createdAt; - - public Tag(String name) { - this.id = UUID.randomUUID().toString(); - this.name = name; - this.createdAt = new DateTime(); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/service/AuthorizationService.java b/.framework/java/backend/src/main/java/io/spring/core/service/AuthorizationService.java deleted file mode 100644 index 080e742..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/service/AuthorizationService.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.spring.core.service; - -import io.spring.core.comment.Comment; -import io.spring.core.item.Item; -import io.spring.core.user.User; - -public class AuthorizationService { - public static boolean canWriteItem(User user, Item item) { - return user.getId().equals(item.getSellerId()); - } - - public static boolean canWriteComment(User user, Item item, Comment comment) { - return user.getId().equals(item.getSellerId()) || user.getId().equals(comment.getSellerId()); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/service/JwtService.java b/.framework/java/backend/src/main/java/io/spring/core/service/JwtService.java deleted file mode 100644 index d143076..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/service/JwtService.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.spring.core.service; - -import io.spring.core.user.User; -import java.util.Optional; -import org.springframework.stereotype.Service; - -@Service -public interface JwtService { - String toToken(User user); - - Optional getSubFromToken(String token); -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/user/FollowRelation.java b/.framework/java/backend/src/main/java/io/spring/core/user/FollowRelation.java deleted file mode 100644 index 7d7b538..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/user/FollowRelation.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.spring.core.user; - -import lombok.Data; -import lombok.NoArgsConstructor; - -@NoArgsConstructor -@Data -public class FollowRelation { - private String userId; - private String targetId; - - public FollowRelation(String userId, String targetId) { - - this.userId = userId; - this.targetId = targetId; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/user/User.java b/.framework/java/backend/src/main/java/io/spring/core/user/User.java deleted file mode 100644 index 3044d50..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/user/User.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.spring.core.user; - -import io.spring.Util; -import java.util.UUID; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -@EqualsAndHashCode(of = {"id"}) -public class User { - private String id; - private String email; - private String username; - private String password; - private String bio; - private String image; - - public User(String email, String username, String password, String bio, String image) { - this.id = UUID.randomUUID().toString(); - this.email = email; - this.username = username; - this.password = password; - this.bio = bio; - this.image = image; - } - - public void update(String email, String username, String password, String bio, String image) { - if (!Util.isEmpty(email)) { - this.email = email; - } - - if (!Util.isEmpty(username)) { - this.username = username; - } - - if (!Util.isEmpty(password)) { - this.password = password; - } - - if (!Util.isEmpty(bio)) { - this.bio = bio; - } - - if (!Util.isEmpty(image)) { - this.image = image; - } - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/core/user/UserRepository.java b/.framework/java/backend/src/main/java/io/spring/core/user/UserRepository.java deleted file mode 100644 index f52c772..0000000 --- a/.framework/java/backend/src/main/java/io/spring/core/user/UserRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.spring.core.user; - -import java.util.Optional; -import org.springframework.stereotype.Repository; - -@Repository -public interface UserRepository { - void save(User user); - - Optional findById(String id); - - Optional findByUsername(String username); - - Optional findByEmail(String email); - - void saveRelation(FollowRelation followRelation); - - Optional findRelation(String userId, String targetId); - - void removeRelation(FollowRelation followRelation); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/DateTimeHandler.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/DateTimeHandler.java deleted file mode 100644 index 19323e5..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/DateTimeHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.spring.infrastructure.mybatis; - -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.TimeZone; -import org.apache.ibatis.type.JdbcType; -import org.apache.ibatis.type.MappedTypes; -import org.apache.ibatis.type.TypeHandler; -import org.joda.time.DateTime; - -@MappedTypes(DateTime.class) -public class DateTimeHandler implements TypeHandler { - - private static final Calendar UTC_CALENDAR = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - - @Override - public void setParameter(PreparedStatement ps, int i, DateTime parameter, JdbcType jdbcType) - throws SQLException { - ps.setTimestamp( - i, parameter != null ? new Timestamp(parameter.getMillis()) : null, UTC_CALENDAR); - } - - @Override - public DateTime getResult(ResultSet rs, String columnName) throws SQLException { - Timestamp timestamp = rs.getTimestamp(columnName, UTC_CALENDAR); - return timestamp != null ? new DateTime(timestamp.getTime()) : null; - } - - @Override - public DateTime getResult(ResultSet rs, int columnIndex) throws SQLException { - Timestamp timestamp = rs.getTimestamp(columnIndex, UTC_CALENDAR); - return timestamp != null ? new DateTime(timestamp.getTime()) : null; - } - - @Override - public DateTime getResult(CallableStatement cs, int columnIndex) throws SQLException { - Timestamp ts = cs.getTimestamp(columnIndex, UTC_CALENDAR); - return ts != null ? new DateTime(ts.getTime()) : null; - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/CommentMapper.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/CommentMapper.java deleted file mode 100644 index 5b7c3cc..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/CommentMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.spring.infrastructure.mybatis.mapper; - -import io.spring.core.comment.Comment; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface CommentMapper { - void insert(@Param("comment") Comment comment); - - Comment findById(@Param("itemId") String itemId, @Param("id") String id); - - void delete(@Param("id") String id); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/ItemFavoriteMapper.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/ItemFavoriteMapper.java deleted file mode 100644 index 4ff92dc..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/ItemFavoriteMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.spring.infrastructure.mybatis.mapper; - -import io.spring.core.favorite.ItemFavorite; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface ItemFavoriteMapper { - ItemFavorite find(@Param("itemId") String itemId, @Param("userId") String userId); - - void insert(@Param("itemFavorite") ItemFavorite itemFavorite); - - void delete(@Param("favorite") ItemFavorite favorite); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/ItemMapper.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/ItemMapper.java deleted file mode 100644 index 8dd8696..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/ItemMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.spring.infrastructure.mybatis.mapper; - -import io.spring.core.item.Item; -import io.spring.core.item.Tag; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.joda.time.DateTime; - -@Mapper -public interface ItemMapper { - void insert(@Param("item") Item item); - - Item findById(@Param("id") String id); - - Tag findTag(@Param("tagName") String tagName); - - void insertTag(@Param("tag") Tag tag); - - void insertItemTagRelation( - @Param("itemId") String itemId, - @Param("tagId") String tagId, - @Param("createdAt") DateTime createdAt); - - Item findBySlug(@Param("slug") String slug); - - void update(@Param("item") Item item); - - void delete(@Param("id") String id); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/UserMapper.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/UserMapper.java deleted file mode 100644 index 54f36c7..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/mapper/UserMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.spring.infrastructure.mybatis.mapper; - -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface UserMapper { - void insert(@Param("user") User user); - - User findByUsername(@Param("username") String username); - - User findByEmail(@Param("email") String email); - - User findById(@Param("id") String id); - - void update(@Param("user") User user); - - FollowRelation findRelation(@Param("userId") String userId, @Param("targetId") String targetId); - - void saveRelation(@Param("followRelation") FollowRelation followRelation); - - void deleteRelation(@Param("followRelation") FollowRelation followRelation); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/CommentReadService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/CommentReadService.java deleted file mode 100644 index 2c27b7c..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/CommentReadService.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.spring.infrastructure.mybatis.readservice; - -import io.spring.application.CursorPageParameter; -import io.spring.application.data.CommentData; -import java.util.List; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.joda.time.DateTime; - -@Mapper -public interface CommentReadService { - CommentData findById(@Param("id") String id); - - List findByItemId(@Param("itemId") String itemId); - - List findByItemIdWithCursor( - @Param("itemId") String itemId, @Param("page") CursorPageParameter page); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/ItemFavoritesReadService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/ItemFavoritesReadService.java deleted file mode 100644 index c913a23..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/ItemFavoritesReadService.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.spring.infrastructure.mybatis.readservice; - -import io.spring.application.data.ItemFavoriteCount; -import io.spring.core.user.User; -import java.util.List; -import java.util.Set; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface ItemFavoritesReadService { - boolean isUserFavorite(@Param("userId") String userId, @Param("itemId") String itemId); - - int itemFavoriteCount(@Param("itemId") String itemId); - - List itemsFavoriteCount(@Param("ids") List ids); - - Set userFavorites(@Param("ids") List ids, @Param("currentUser") User currentUser); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/ItemReadService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/ItemReadService.java deleted file mode 100644 index e8198f9..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/ItemReadService.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.spring.infrastructure.mybatis.readservice; - -import io.spring.application.CursorPageParameter; -import io.spring.application.Page; -import io.spring.application.data.ItemData; -import java.util.List; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface ItemReadService { - ItemData findById(@Param("id") String id); - - ItemData findBySlug(@Param("slug") String slug); - - List queryItems( - @Param("tag") String tag, - @Param("seller") String seller, - @Param("favoritedBy") String favoritedBy, - @Param("page") Page page); - - int countItem( - @Param("tag") String tag, - @Param("seller") String seller, - @Param("favoritedBy") String favoritedBy); - - List findItems(@Param("itemIds") List itemIds); - - List findItemsOfSellers( - @Param("sellers") List authors, @Param("page") Page page); - - List findItemsOfSellersWithCursor( - @Param("sellers") List authors, @Param("page") CursorPageParameter page); - - int countFeedSize(@Param("sellers") List sellers); - - List findItemsWithCursor( - @Param("tag") String tag, - @Param("seller") String seller, - @Param("favoritedBy") String favoritedBy, - @Param("page") CursorPageParameter page); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/TagReadService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/TagReadService.java deleted file mode 100644 index 8737687..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/TagReadService.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.spring.infrastructure.mybatis.readservice; - -import java.util.List; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface TagReadService { - List all(); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/UserReadService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/UserReadService.java deleted file mode 100644 index ae25a48..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/UserReadService.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.spring.infrastructure.mybatis.readservice; - -import io.spring.application.data.UserData; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface UserReadService { - - UserData findByUsername(@Param("username") String username); - - UserData findById(@Param("id") String id); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/UserRelationshipQueryService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/UserRelationshipQueryService.java deleted file mode 100644 index 4a8b230..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/mybatis/readservice/UserRelationshipQueryService.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.spring.infrastructure.mybatis.readservice; - -import java.util.List; -import java.util.Set; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -@Mapper -public interface UserRelationshipQueryService { - boolean isUserFollowing( - @Param("userId") String userId, @Param("anotherUserId") String anotherUserId); - - Set followingSellers(@Param("userId") String userId, @Param("ids") List ids); - - List followedUsers(@Param("userId") String userId); -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisCommentRepository.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisCommentRepository.java deleted file mode 100644 index e0d33e3..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisCommentRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.spring.infrastructure.repository; - -import io.spring.core.comment.Comment; -import io.spring.core.comment.CommentRepository; -import io.spring.infrastructure.mybatis.mapper.CommentMapper; -import java.util.Optional; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class MyBatisCommentRepository implements CommentRepository { - private CommentMapper commentMapper; - - @Autowired - public MyBatisCommentRepository(CommentMapper commentMapper) { - this.commentMapper = commentMapper; - } - - @Override - public void save(Comment comment) { - commentMapper.insert(comment); - } - - @Override - public Optional findById(String itemId, String id) { - return Optional.ofNullable(commentMapper.findById(itemId, id)); - } - - @Override - public void remove(Comment comment) { - commentMapper.delete(comment.getId()); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisItemFavoriteRepository.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisItemFavoriteRepository.java deleted file mode 100644 index 138bc99..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisItemFavoriteRepository.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.spring.infrastructure.repository; - -import io.spring.core.favorite.ItemFavorite; -import io.spring.core.favorite.ItemFavoriteRepository; -import io.spring.infrastructure.mybatis.mapper.ItemFavoriteMapper; -import java.util.Optional; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class MyBatisItemFavoriteRepository implements ItemFavoriteRepository { - private ItemFavoriteMapper mapper; - - @Autowired - public MyBatisItemFavoriteRepository(ItemFavoriteMapper mapper) { - this.mapper = mapper; - } - - @Override - public void save(ItemFavorite itemFavorite) { - if (mapper.find(itemFavorite.getItemId(), itemFavorite.getUserId()) == null) { - mapper.insert(itemFavorite); - } - } - - @Override - public Optional find(String itemId, String userId) { - return Optional.ofNullable(mapper.find(itemId, userId)); - } - - @Override - public void remove(ItemFavorite favorite) { - mapper.delete(favorite); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisItemRepository.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisItemRepository.java deleted file mode 100644 index 1f30b58..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisItemRepository.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.spring.infrastructure.repository; - -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.item.Tag; -import io.spring.infrastructure.mybatis.mapper.ItemMapper; -import java.util.Optional; -import org.joda.time.DateTime; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -@Repository -public class MyBatisItemRepository implements ItemRepository { - private ItemMapper itemMapper; - - public MyBatisItemRepository(ItemMapper itemMapper) { - this.itemMapper = itemMapper; - } - - @Override - @Transactional - public void save(Item item) { - if (itemMapper.findById(item.getId()) == null) { - createNew(item); - } else { - itemMapper.update(item); - } - } - - private void createNew(Item item) { - for (Tag tag : item.getTags()) { - Tag targetTag = - Optional.ofNullable(itemMapper.findTag(tag.getName())) - .orElseGet( - () -> { - itemMapper.insertTag(tag); - return tag; - }); - - itemMapper.insertItemTagRelation(item.getId(), targetTag.getId(), new DateTime()); - } - itemMapper.insert(item); - } - - @Override - public Optional findById(String id) { - return Optional.ofNullable(itemMapper.findById(id)); - } - - @Override - public Optional findBySlug(String slug) { - return Optional.ofNullable(itemMapper.findBySlug(slug)); - } - - @Override - public void remove(Item item) { - itemMapper.delete(item.getId()); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisUserRepository.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisUserRepository.java deleted file mode 100644 index 3c24dd5..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/repository/MyBatisUserRepository.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.spring.infrastructure.repository; - -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.mybatis.mapper.UserMapper; -import java.util.Optional; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class MyBatisUserRepository implements UserRepository { - private final UserMapper userMapper; - - @Autowired - public MyBatisUserRepository(UserMapper userMapper) { - this.userMapper = userMapper; - } - - @Override - public void save(User user) { - if (userMapper.findById(user.getId()) == null) { - userMapper.insert(user); - } else { - userMapper.update(user); - } - } - - @Override - public Optional findById(String id) { - return Optional.ofNullable(userMapper.findById(id)); - } - - @Override - public Optional findByUsername(String username) { - return Optional.ofNullable(userMapper.findByUsername(username)); - } - - @Override - public Optional findByEmail(String email) { - return Optional.ofNullable(userMapper.findByEmail(email)); - } - - @Override - public void saveRelation(FollowRelation followRelation) { - if (!findRelation(followRelation.getUserId(), followRelation.getTargetId()).isPresent()) { - userMapper.saveRelation(followRelation); - } - } - - @Override - public Optional findRelation(String userId, String targetId) { - return Optional.ofNullable(userMapper.findRelation(userId, targetId)); - } - - @Override - public void removeRelation(FollowRelation followRelation) { - userMapper.deleteRelation(followRelation); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/service/DefaultJwtService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/service/DefaultJwtService.java deleted file mode 100644 index 515d661..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/service/DefaultJwtService.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.spring.infrastructure.service; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import io.spring.core.service.JwtService; -import io.spring.core.user.User; -import java.util.Date; -import java.util.Optional; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -@Component -public class DefaultJwtService implements JwtService { - private final SecretKey signingKey; - private final SignatureAlgorithm signatureAlgorithm; - private int sessionTime; - - @Autowired - public DefaultJwtService( - @Value("${jwt.secret}") String secret, @Value("${jwt.sessionTime}") int sessionTime) { - this.sessionTime = sessionTime; - signatureAlgorithm = SignatureAlgorithm.HS512; - this.signingKey = new SecretKeySpec(secret.getBytes(), signatureAlgorithm.getJcaName()); - } - - @Override - public String toToken(User user) { - return Jwts.builder() - .setSubject(user.getId()) - .setExpiration(expireTimeFromNow()) - .signWith(signingKey) - .compact(); - } - - @Override - public Optional getSubFromToken(String token) { - try { - Jws claimsJws = - Jwts.parserBuilder().setSigningKey(signingKey).build().parseClaimsJws(token); - return Optional.ofNullable(claimsJws.getBody().getSubject()); - } catch (Exception e) { - return Optional.empty(); - } - } - - private Date expireTimeFromNow() { - return new Date(System.currentTimeMillis() + sessionTime * 1000L); - } -} diff --git a/.framework/java/backend/src/main/java/io/spring/infrastructure/service/SendEventService.java b/.framework/java/backend/src/main/java/io/spring/infrastructure/service/SendEventService.java deleted file mode 100644 index 401704d..0000000 --- a/.framework/java/backend/src/main/java/io/spring/infrastructure/service/SendEventService.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.spring.infrastructure.service; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.util.Map; -import java.util.Objects; -import okhttp3.*; - -public class SendEventService { - - private static final String PATH_TO_WILCO_ID = "../.wilco"; - private static final String BASE_URL = - Objects.requireNonNullElse(System.getenv("ENGINE_BASE_URL"), "https://engine.wilco.gg"); - private static String wilcoId; - - private final OkHttpClient client; - private final ObjectMapper objectMapper; - - public SendEventService() { - this.client = new OkHttpClient(); - this.objectMapper = new ObjectMapper(); - this.wilcoId = System.getenv("WILCO_ID"); - - if (wilcoId == null && doesFileExist(PATH_TO_WILCO_ID)) { - wilcoId = readFile(PATH_TO_WILCO_ID); - } - } - - public String sendEvent(String event, Map metadata) { - MediaType mediaType = MediaType.parse("application/json"); - - JsonNode metadataNode = objectMapper.valueToTree(metadata); - - ObjectNode data = objectMapper.createObjectNode(); - data.put("event", event); - data.set("metadata", metadataNode); - - RequestBody requestBody = RequestBody.create(mediaType, data.toString()); - - Request request = - new Request.Builder() - .url(BASE_URL + "/users/" + wilcoId + "/event") - .post(requestBody) - .addHeader("Content-type", "application/json") - .build(); - - try { - Response response = client.newCall(request).execute(); - return response.body().string(); - } catch (IOException e) { - e.printStackTrace(); - System.err.println("Failed to send event " + event + " to Wilco engine"); - return null; - } - } - - private static boolean doesFileExist(String filePath) { - return Objects.requireNonNull(new java.io.File(filePath).exists()); - } - - private static String readFile(String filePath) { - StringBuilder content = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { - String line; - while ((line = reader.readLine()) != null) { - content.append(line); - } - } catch (IOException e) { - e.printStackTrace(); - } - return content.toString(); - } -} diff --git a/.framework/java/backend/src/main/resources/application-test.properties b/.framework/java/backend/src/main/resources/application-test.properties deleted file mode 100644 index 612f0b6..0000000 --- a/.framework/java/backend/src/main/resources/application-test.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password diff --git a/.framework/java/backend/src/main/resources/application.properties b/.framework/java/backend/src/main/resources/application.properties deleted file mode 100644 index 4319b5e..0000000 --- a/.framework/java/backend/src/main/resources/application.properties +++ /dev/null @@ -1,24 +0,0 @@ -spring.datasource.url=jdbc:postgresql://postgres-java:5432/anythink-market -spring.datasource.username=postgres -spring.datasource.password= -spring.datasource.driver-class-name=org.postgresql.Driver -spring.jackson.deserialization.UNWRAP_ROOT_VALUE=true - -image.default=https://static.productionready.io/images/smiley-cyrus.jpg - -jwt.secret=nRvyYC4soFxBdZ-F-5Nnzz5USXstR1YylsTd-mA0aKtI9HUlriGrtkf-TiuDapkLiUCogO3JOK7kwZisrHp6wA -jwt.sessionTime=86400 - -mybatis.configuration.cache-enabled=true -mybatis.configuration.default-statement-timeout=3000 -mybatis.configuration.map-underscore-to-camel-case=true -mybatis.configuration.use-generated-keys=true -mybatis.type-handlers-package=io.spring.infrastructure.mybatis -mybatis.mapper-locations=mapper/*.xml - -logging.level.io.spring.infrastructure.mybatis.readservice.ItemReadService=DEBUG -logging.level.io.spring.infrastructure.mybatis.mapper=DEBUG - -server.port=3000 - -management.endpoints.web.base-path=/ diff --git a/.framework/java/backend/src/main/resources/db/migration/V1__create_tables.sql b/.framework/java/backend/src/main/resources/db/migration/V1__create_tables.sql deleted file mode 100644 index 1a5b612..0000000 --- a/.framework/java/backend/src/main/resources/db/migration/V1__create_tables.sql +++ /dev/null @@ -1,50 +0,0 @@ -create table users ( - id varchar(255) primary key, - username varchar(255) UNIQUE, - password varchar(255), - email varchar(255) UNIQUE, - bio text, - image varchar(511) -); - -create table items ( - id varchar(255) primary key, - seller_id varchar(255), - slug varchar(255) UNIQUE, - title varchar(255), - description text, - image text, - created_at TIMESTAMP NOT NULL, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP -); - -create table item_favorites ( - item_id varchar(255) not null, - user_id varchar(255) not null, - primary key(item_id, user_id) -); - -create table follows ( - user_id varchar(255) not null, - follow_id varchar(255) not null -); - -create table tags ( - id varchar(255) primary key, - name varchar(255) not null -); - -create table item_tags ( - item_id varchar(255) not null, - tag_id varchar(255) not null, - created_at TIMESTAMP not null -); - -create table comments ( - id varchar(255) primary key, - body text, - item_id varchar(255), - seller_id varchar(255), - created_at TIMESTAMP NOT NULL, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP -); diff --git a/.framework/java/backend/src/main/resources/mapper/CommentMapper.xml b/.framework/java/backend/src/main/resources/mapper/CommentMapper.xml deleted file mode 100644 index c715304..0000000 --- a/.framework/java/backend/src/main/resources/mapper/CommentMapper.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - insert into comments(id, body, seller_id, item_id, created_at, updated_at) - values ( - #{comment.id}, - #{comment.body}, - #{comment.sellerId}, - #{comment.itemId}, - #{comment.createdAt}, - #{comment.createdAt} - ) - - - delete from comments where id = #{id} - - - - - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/CommentReadService.xml b/.framework/java/backend/src/main/resources/mapper/CommentReadService.xml deleted file mode 100644 index cebb77e..0000000 --- a/.framework/java/backend/src/main/resources/mapper/CommentReadService.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - SELECT - C.id commentId, - C.body commentBody, - C.created_at commentCreatedAt, - C.item_id commentItemId, - - from comments C - left join users U - on C.seller_id = U.id - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/ItemFavoriteMapper.xml b/.framework/java/backend/src/main/resources/mapper/ItemFavoriteMapper.xml deleted file mode 100644 index 5fbba91..0000000 --- a/.framework/java/backend/src/main/resources/mapper/ItemFavoriteMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - insert into item_favorites (item_id, user_id) values (#{itemFavorite.itemId}, #{itemFavorite.userId}) - - - delete from item_favorites where item_id = #{favorite.itemId} and user_id = #{favorite.userId} - - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/ItemFavoritesReadService.xml b/.framework/java/backend/src/main/resources/mapper/ItemFavoritesReadService.xml deleted file mode 100644 index 16a673f..0000000 --- a/.framework/java/backend/src/main/resources/mapper/ItemFavoritesReadService.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/ItemMapper.xml b/.framework/java/backend/src/main/resources/mapper/ItemMapper.xml deleted file mode 100644 index f907a17..0000000 --- a/.framework/java/backend/src/main/resources/mapper/ItemMapper.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - insert into items(id, slug, title, description, image, seller_id, created_at, updated_at) - values( - #{item.id}, - #{item.slug}, - #{item.title}, - #{item.description}, - #{item.image}, - #{item.sellerId}, - #{item.createdAt}, - #{item.updatedAt}) - - - insert into tags (id, name) values (#{tag.id}, #{tag.name}) - - - insert into item_tags (item_id, tag_id, created_at) values(#{itemId}, #{tagId}, #{createdAt}) - - - update items - - title = #{item.title}, - slug = #{item.slug}, - description = #{item.description}, - image = #{item.image} - - where id = #{item.id} - - - delete from items where id = #{id} - - - select - A.id itemId, - A.slug itemSlug, - A.title itemTitle, - A.description itemDescription, - A.image itemImage, - A.seller_id itemSellerId, - A.created_at itemCreatedAt, - A.updated_at itemUpdatedAt, - T.id tagId, - T.name tagName - from items A - left join item_tags AT on A.id = AT.item_id - left join tags T on T.id = AT.tag_id - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/ItemReadService.xml b/.framework/java/backend/src/main/resources/mapper/ItemReadService.xml deleted file mode 100644 index 2740017..0000000 --- a/.framework/java/backend/src/main/resources/mapper/ItemReadService.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - - - U.id userId, - U.username userUsername, - U.bio userBio, - U.image userImage - - - select - A.id itemId, - A.slug itemSlug, - A.title itemTitle, - A.description itemDescription, - A.image itemImage, - A.created_at itemCreatedAt, - A.updated_at itemUpdatedAt, - T.name tagName, - - from - items A - left join item_tags AT on A.id = AT.item_id - left join tags T on T.id = AT.tag_id - left join users U on U.id = A.seller_id - - - select - DISTINCT(A.id) itemId, A.created_at - from - items A - left join item_tags AT on A.id = AT.item_id - left join tags T on T.id = AT.tag_id - left join item_favorites AF on AF.item_id = A.id - left join users AU on AU.id = A.seller_id - left join users AFU on AFU.id = AF.user_id - - - - - - - - - - - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/TagReadService.xml b/.framework/java/backend/src/main/resources/mapper/TagReadService.xml deleted file mode 100644 index 0e8ceef..0000000 --- a/.framework/java/backend/src/main/resources/mapper/TagReadService.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.framework/java/backend/src/main/resources/mapper/TransferData.xml b/.framework/java/backend/src/main/resources/mapper/TransferData.xml deleted file mode 100644 index 45bcd8d..0000000 --- a/.framework/java/backend/src/main/resources/mapper/TransferData.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.framework/java/backend/src/main/resources/mapper/UserMapper.xml b/.framework/java/backend/src/main/resources/mapper/UserMapper.xml deleted file mode 100644 index 08e89b2..0000000 --- a/.framework/java/backend/src/main/resources/mapper/UserMapper.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - insert into users (id, username, email, password, bio, image) values( - #{user.id}, - #{user.username}, - #{user.email}, - #{user.password}, - #{user.bio}, - #{user.image} - ) - - - insert into follows(user_id, follow_id) values (#{followRelation.userId}, #{followRelation.targetId}) - - - update users - - username = #{user.username}, - email = #{user.email}, - password = #{user.password}, - bio = #{user.bio}, - image = #{user.image} - - where id = #{user.id} - - - delete from follows where user_id = #{followRelation.userId} and follow_id = #{followRelation.targetId} - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.framework/java/backend/src/main/resources/mapper/UserReadService.xml b/.framework/java/backend/src/main/resources/mapper/UserReadService.xml deleted file mode 100644 index edf53c1..0000000 --- a/.framework/java/backend/src/main/resources/mapper/UserReadService.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.framework/java/backend/src/main/resources/mapper/UserRelationshipQueryService.xml b/.framework/java/backend/src/main/resources/mapper/UserRelationshipQueryService.xml deleted file mode 100644 index 8bed754..0000000 --- a/.framework/java/backend/src/main/resources/mapper/UserRelationshipQueryService.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/.framework/java/backend/src/test/java/io/spring/AnythinkMarketApplicationTests.java b/.framework/java/backend/src/test/java/io/spring/AnythinkMarketApplicationTests.java deleted file mode 100644 index cd81530..0000000 --- a/.framework/java/backend/src/test/java/io/spring/AnythinkMarketApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.spring; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; - -@ActiveProfiles("test") -@SpringBootTest() -public class AnythinkMarketApplicationTests { - - @Test - public void contextLoads() {} -} diff --git a/.framework/java/backend/src/test/java/io/spring/TestHelper.java b/.framework/java/backend/src/test/java/io/spring/TestHelper.java deleted file mode 100644 index 3dd29f2..0000000 --- a/.framework/java/backend/src/test/java/io/spring/TestHelper.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.spring; - -import io.spring.application.data.ItemData; -import io.spring.application.data.ProfileData; -import io.spring.core.item.Item; -import io.spring.core.user.User; -import java.util.ArrayList; -import java.util.Arrays; -import org.joda.time.DateTime; - -public class TestHelper { - public static ItemData itemDataFixture(String seed, User user) { - DateTime now = new DateTime(); - return new ItemData( - seed + "id", - "title-" + seed, - "title " + seed, - "desc " + seed, - "image" + seed, - false, - 0, - now, - now, - new ArrayList<>(), - new ProfileData(user.getId(), user.getUsername(), user.getBio(), user.getImage(), false)); - } - - public static ItemData getItemDataFromItemAndUser(Item item, User user) { - return new ItemData( - item.getId(), - item.getSlug(), - item.getTitle(), - item.getDescription(), - item.getImage(), - false, - 0, - item.getCreatedAt(), - item.getUpdatedAt(), - Arrays.asList("joda"), - new ProfileData(user.getId(), user.getUsername(), user.getBio(), user.getImage(), false)); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/CommentsApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/CommentsApiTest.java deleted file mode 100644 index c13246e..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/CommentsApiTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.CommentQueryService; -import io.spring.application.data.CommentData; -import io.spring.application.data.ProfileData; -import io.spring.core.comment.Comment; -import io.spring.core.comment.CommentRepository; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest(CommentsApi.class) -@Import({WebSecurityConfig.class, JacksonCustomizations.class}) -public class CommentsApiTest extends TestWithCurrentUser { - - @MockBean private ItemRepository itemRepository; - - @MockBean private CommentRepository commentRepository; - @MockBean private CommentQueryService commentQueryService; - - private Item item; - private CommentData commentData; - private Comment comment; - @Autowired private MockMvc mvc; - - @BeforeEach - public void setUp() throws Exception { - RestAssuredMockMvc.mockMvc(mvc); - super.setUp(); - item = new Item("title", "desc", "image", Arrays.asList("test", "java"), user.getId()); - when(itemRepository.findBySlug(eq(item.getSlug()))).thenReturn(Optional.of(item)); - comment = new Comment("comment", user.getId(), item.getId()); - commentData = - new CommentData( - comment.getId(), - comment.getBody(), - comment.getItemId(), - comment.getCreatedAt(), - comment.getCreatedAt(), - new ProfileData( - user.getId(), user.getUsername(), user.getBio(), user.getImage(), false)); - } - - @Test - public void should_create_comment_success() throws Exception { - Map param = - new HashMap() { - { - put( - "comment", - new HashMap() { - { - put("body", "comment content"); - } - }); - } - }; - - when(commentQueryService.findById(anyString(), eq(user))).thenReturn(Optional.of(commentData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .post("/api/items/{slug}/comments", item.getSlug()) - .then() - .statusCode(201) - .body("comment.body", equalTo(commentData.getBody())); - } - - @Test - public void should_get_422_with_empty_body() throws Exception { - Map param = - new HashMap() { - { - put( - "comment", - new HashMap() { - { - put("body", ""); - } - }); - } - }; - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .post("/api/items/{slug}/comments", item.getSlug()) - .then() - .statusCode(422) - .body("errors.body[0]", equalTo("can't be empty")); - } - - @Test - public void should_get_comments_of_item_success() throws Exception { - when(commentQueryService.findByItemId(anyString(), eq(null))) - .thenReturn(Arrays.asList(commentData)); - RestAssuredMockMvc.when() - .get("/api/items/{slug}/comments", item.getSlug()) - .prettyPeek() - .then() - .statusCode(200) - .body("comments[0].id", equalTo(commentData.getId())); - } - - @Test - public void should_delete_comment_success() throws Exception { - when(commentRepository.findById(eq(item.getId()), eq(comment.getId()))) - .thenReturn(Optional.of(comment)); - - given() - .header("Authorization", "Token " + token) - .when() - .delete("/api/items/{slug}/comments/{id}", item.getSlug(), comment.getId()) - .then() - .statusCode(204); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/CurrentUserApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/CurrentUserApiTest.java deleted file mode 100644 index e00e05c..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/CurrentUserApiTest.java +++ /dev/null @@ -1,179 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.UserQueryService; -import io.spring.application.user.UserService; -import io.spring.core.user.User; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest(CurrentUserApi.class) -@Import({ - WebSecurityConfig.class, - JacksonCustomizations.class, - UserService.class, - ValidationAutoConfiguration.class, - BCryptPasswordEncoder.class -}) -public class CurrentUserApiTest extends TestWithCurrentUser { - - @Autowired private MockMvc mvc; - - @MockBean private UserQueryService userQueryService; - - @Override - @BeforeEach - public void setUp() throws Exception { - super.setUp(); - RestAssuredMockMvc.mockMvc(mvc); - } - - @Test - public void should_get_current_user_with_token() throws Exception { - when(userQueryService.findById(any())).thenReturn(Optional.of(userData)); - - given() - .header("Authorization", "Token " + token) - .contentType("application/json") - .when() - .get("/api/user") - .then() - .statusCode(200) - .body("user.email", equalTo(email)) - .body("user.username", equalTo(username)) - .body("user.bio", equalTo("")) - .body("user.image", equalTo(defaultAvatar)) - .body("user.token", equalTo(token)); - } - - @Test - public void should_get_401_without_token() throws Exception { - given().contentType("application/json").when().get("/api/user").then().statusCode(401); - } - - @Test - public void should_get_401_with_invalid_token() throws Exception { - String invalidToken = "asdfasd"; - when(jwtService.getSubFromToken(eq(invalidToken))).thenReturn(Optional.empty()); - given() - .contentType("application/json") - .header("Authorization", "Token " + invalidToken) - .when() - .get("/api/user") - .then() - .statusCode(401); - } - - @Test - public void should_update_current_user_profile() throws Exception { - String newEmail = "newemail@example.com"; - String newBio = "updated"; - String newUsername = "newusernamee"; - - Map param = - new HashMap() { - { - put( - "user", - new HashMap() { - { - put("email", newEmail); - put("bio", newBio); - put("username", newUsername); - } - }); - } - }; - - when(userRepository.findByUsername(eq(newUsername))).thenReturn(Optional.empty()); - when(userRepository.findByEmail(eq(newEmail))).thenReturn(Optional.empty()); - - when(userQueryService.findById(eq(user.getId()))).thenReturn(Optional.of(userData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .put("/api/user") - .then() - .statusCode(200); - } - - @Test - public void should_get_error_if_email_exists_when_update_user_profile() throws Exception { - String newEmail = "newemail@example.com"; - String newBio = "updated"; - String newUsername = "newusernamee"; - - Map param = prepareUpdateParam(newEmail, newBio, newUsername); - - when(userRepository.findByEmail(eq(newEmail))) - .thenReturn(Optional.of(new User(newEmail, "username", "123", "", ""))); - when(userRepository.findByUsername(eq(newUsername))).thenReturn(Optional.empty()); - - when(userQueryService.findById(eq(user.getId()))).thenReturn(Optional.of(userData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .put("/api/user") - .prettyPeek() - .then() - .statusCode(422) - .body("errors.email[0]", equalTo("email already exist")); - } - - private HashMap prepareUpdateParam( - final String newEmail, final String newBio, final String newUsername) { - return new HashMap() { - { - put( - "user", - new HashMap() { - { - put("email", newEmail); - put("bio", newBio); - put("username", newUsername); - } - }); - } - }; - } - - @Test - public void should_get_401_if_not_login() throws Exception { - given() - .contentType("application/json") - .body( - new HashMap() { - { - put("user", new HashMap()); - } - }) - .when() - .put("/api/user") - .then() - .statusCode(401); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/ItemApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/ItemApiTest.java deleted file mode 100644 index c521582..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/ItemApiTest.java +++ /dev/null @@ -1,222 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.TestHelper; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.ItemQueryService; -import io.spring.application.data.ItemData; -import io.spring.application.data.ProfileData; -import io.spring.application.item.ItemCommandService; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.User; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest({ItemApi.class}) -@Import({WebSecurityConfig.class, JacksonCustomizations.class}) -public class ItemApiTest extends TestWithCurrentUser { - @Autowired private MockMvc mvc; - - @MockBean private ItemQueryService itemQueryService; - - @MockBean private ItemRepository itemRepository; - - @MockBean ItemCommandService itemCommandService; - - @Override - @BeforeEach - public void setUp() throws Exception { - super.setUp(); - RestAssuredMockMvc.mockMvc(mvc); - } - - @Test - public void should_read_item_success() throws Exception { - String slug = "test-new-item"; - DateTime time = new DateTime(); - Item item = - new Item( - "Test New Item", - "Desc", - "Image", - Arrays.asList("java", "spring", "jpg"), - user.getId(), - time); - ItemData itemData = TestHelper.getItemDataFromItemAndUser(item, user); - - when(itemQueryService.findBySlug(eq(slug), eq(null))).thenReturn(Optional.of(itemData)); - - RestAssuredMockMvc.when() - .get("/api/items/{slug}", slug) - .then() - .statusCode(200) - .body("item.slug", equalTo(slug)) - .body("item.image", equalTo(itemData.getImage())) - .body("item.createdAt", equalTo(ISODateTimeFormat.dateTime().withZoneUTC().print(time))); - } - - @Test - public void should_404_if_item_not_found() throws Exception { - when(itemQueryService.findBySlug(anyString(), any())).thenReturn(Optional.empty()); - RestAssuredMockMvc.when().get("/api/items/not-exists").then().statusCode(404); - } - - @Test - public void should_update_item_content_success() throws Exception { - List tagList = Arrays.asList("java", "spring", "jpg"); - - Item originalItem = - new Item("old title", "old description", "old image", tagList, user.getId()); - - Item updatedItem = new Item("new title", "new description", "old image", tagList, user.getId()); - - Map updateParam = - prepareUpdateParam( - updatedItem.getTitle(), updatedItem.getImage(), updatedItem.getDescription()); - - ItemData updatedItemData = TestHelper.getItemDataFromItemAndUser(updatedItem, user); - - when(itemRepository.findBySlug(eq(originalItem.getSlug()))) - .thenReturn(Optional.of(originalItem)); - when(itemCommandService.updateItem(eq(originalItem), any())).thenReturn(updatedItem); - when(itemQueryService.findBySlug(eq(updatedItem.getSlug()), eq(user))) - .thenReturn(Optional.of(updatedItemData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(updateParam) - .when() - .put("/api/items/{slug}", originalItem.getSlug()) - .then() - .statusCode(200) - .body("item.slug", equalTo(updatedItemData.getSlug())); - } - - @Test - public void should_get_403_if_not_user_to_update_item() throws Exception { - String title = "new-title"; - String image = "new image"; - String description = "new description"; - Map updateParam = prepareUpdateParam(title, image, description); - - User anotherUser = new User("test@test.com", "test", "123123", "", ""); - - Item item = - new Item( - title, description, image, Arrays.asList("java", "spring", "jpg"), anotherUser.getId()); - - DateTime time = new DateTime(); - ItemData itemData = - new ItemData( - item.getId(), - item.getSlug(), - item.getTitle(), - item.getDescription(), - item.getImage(), - false, - 0, - time, - time, - Arrays.asList("joda"), - new ProfileData( - anotherUser.getId(), - anotherUser.getUsername(), - anotherUser.getBio(), - anotherUser.getImage(), - false)); - - when(itemRepository.findBySlug(eq(item.getSlug()))).thenReturn(Optional.of(item)); - when(itemQueryService.findBySlug(eq(item.getSlug()), eq(user))) - .thenReturn(Optional.of(itemData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(updateParam) - .when() - .put("/api/items/{slug}", item.getSlug()) - .then() - .statusCode(403); - } - - @Test - public void should_delete_item_success() throws Exception { - String title = "title"; - String image = "image"; - String description = "description"; - - Item item = - new Item(title, description, image, Arrays.asList("java", "spring", "jpg"), user.getId()); - when(itemRepository.findBySlug(eq(item.getSlug()))).thenReturn(Optional.of(item)); - - given() - .header("Authorization", "Token " + token) - .when() - .delete("/api/items/{slug}", item.getSlug()) - .then() - .statusCode(204); - - verify(itemRepository).remove(eq(item)); - } - - @Test - public void should_403_if_not_author_delete_item() throws Exception { - String title = "new-title"; - String image = "new image"; - String description = "new description"; - - User anotherUser = new User("test@test.com", "test", "123123", "", ""); - - Item item = - new Item( - title, description, image, Arrays.asList("java", "spring", "jpg"), anotherUser.getId()); - - when(itemRepository.findBySlug(eq(item.getSlug()))).thenReturn(Optional.of(item)); - given() - .header("Authorization", "Token " + token) - .when() - .delete("/api/items/{slug}", item.getSlug()) - .then() - .statusCode(403); - } - - private HashMap prepareUpdateParam( - final String title, final String image, final String description) { - return new HashMap() { - { - put( - "item", - new HashMap() { - { - put("title", title); - put("image", image); - put("description", description); - } - }); - } - }; - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/ItemFavoriteApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/ItemFavoriteApiTest.java deleted file mode 100644 index 5455a3c..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/ItemFavoriteApiTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.ItemQueryService; -import io.spring.application.data.ItemData; -import io.spring.application.data.ProfileData; -import io.spring.core.favorite.ItemFavorite; -import io.spring.core.favorite.ItemFavoriteRepository; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.item.Tag; -import io.spring.core.user.User; -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest(ItemFavoriteApi.class) -@Import({WebSecurityConfig.class, JacksonCustomizations.class}) -public class ItemFavoriteApiTest extends TestWithCurrentUser { - @Autowired private MockMvc mvc; - - @MockBean private ItemFavoriteRepository itemFavoriteRepository; - - @MockBean private ItemRepository itemRepository; - - @MockBean private ItemQueryService itemQueryService; - - private Item item; - - @BeforeEach - public void setUp() throws Exception { - super.setUp(); - RestAssuredMockMvc.mockMvc(mvc); - User anotherUser = new User("other@test.com", "other", "123", "", ""); - item = new Item("title", "desc", "image", Arrays.asList("java"), anotherUser.getId()); - when(itemRepository.findBySlug(eq(item.getSlug()))).thenReturn(Optional.of(item)); - ItemData itemData = - new ItemData( - item.getId(), - item.getSlug(), - item.getTitle(), - item.getDescription(), - item.getImage(), - true, - 1, - item.getCreatedAt(), - item.getUpdatedAt(), - item.getTags().stream().map(Tag::getName).collect(Collectors.toList()), - new ProfileData( - anotherUser.getId(), - anotherUser.getUsername(), - anotherUser.getBio(), - anotherUser.getImage(), - false)); - when(itemQueryService.findBySlug(eq(itemData.getSlug()), eq(user))) - .thenReturn(Optional.of(itemData)); - } - - @Test - public void should_favorite_an_item_success() throws Exception { - given() - .header("Authorization", "Token " + token) - .when() - .post("/api/items/{slug}/favorite", item.getSlug()) - .prettyPeek() - .then() - .statusCode(200) - .body("item.id", equalTo(item.getId())); - - verify(itemFavoriteRepository).save(any()); - } - - @Test - public void should_unfavorite_an_item_success() throws Exception { - when(itemFavoriteRepository.find(eq(item.getId()), eq(user.getId()))) - .thenReturn(Optional.of(new ItemFavorite(item.getId(), user.getId()))); - given() - .header("Authorization", "Token " + token) - .when() - .delete("/api/items/{slug}/favorite", item.getSlug()) - .prettyPeek() - .then() - .statusCode(200) - .body("item.id", equalTo(item.getId())); - verify(itemFavoriteRepository).remove(new ItemFavorite(item.getId(), user.getId())); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/ItemsApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/ItemsApiTest.java deleted file mode 100644 index bc02966..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/ItemsApiTest.java +++ /dev/null @@ -1,174 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static java.util.Arrays.asList; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.ItemQueryService; -import io.spring.application.data.ItemData; -import io.spring.application.data.ProfileData; -import io.spring.application.item.ItemCommandService; -import io.spring.core.item.Item; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.joda.time.DateTime; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest({ItemsApi.class}) -@Import({WebSecurityConfig.class, JacksonCustomizations.class}) -public class ItemsApiTest extends TestWithCurrentUser { - @Autowired private MockMvc mvc; - - @MockBean private ItemQueryService itemQueryService; - - @MockBean private ItemCommandService itemCommandService; - - @Override - @BeforeEach - public void setUp() throws Exception { - super.setUp(); - RestAssuredMockMvc.mockMvc(mvc); - } - - @Test - public void should_create_item_success() throws Exception { - String title = "How to train your dragon"; - String slug = "how-to-train-your-dragon"; - String description = "Ever wonder how?"; - String image = "Another image"; - List tagList = asList("reactjs", "angularjs", "dragons"); - Map param = prepareParam(title, description, image, tagList); - - ItemData itemData = - new ItemData( - "123", - slug, - title, - description, - image, - false, - 0, - new DateTime(), - new DateTime(), - tagList, - new ProfileData("userid", user.getUsername(), user.getBio(), user.getImage(), false)); - - when(itemCommandService.createItem(any(), any())) - .thenReturn(new Item(title, description, image, tagList, user.getId())); - - when(itemQueryService.findBySlug(eq(Item.toSlug(title)), any())).thenReturn(Optional.empty()); - - when(itemQueryService.findById(any(), any())).thenReturn(Optional.of(itemData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .post("/api/items") - .then() - .statusCode(200) - .body("item.title", equalTo(title)) - .body("item.favorited", equalTo(false)) - .body("item.favoritesCount", equalTo(0)) - .body("item.seller.username", equalTo(user.getUsername())) - .body("item.seller.id", equalTo(null)); - - verify(itemCommandService).createItem(any(), any()); - } - - @Test - public void should_get_error_message_with_wrong_parameter() throws Exception { - String title = ""; - String description = "Ever wonder how?"; - String image = "Image URL"; - String[] tagList = {"reactjs", "angularjs", "dragons"}; - Map param = prepareParam(title, description, image, asList(tagList)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .post("/api/items") - .prettyPeek() - .then() - .statusCode(422) - .body("errors.title[0]", equalTo("can't be empty")); - } - - @Test - public void should_get_error_message_with_duplicated_title() { - String title = "How to train your dragon"; - String slug = "how-to-train-your-dragon"; - String description = "Ever wonder how?"; - String image = "Image URL"; - String[] tagList = {"reactjs", "angularjs", "dragons"}; - Map param = prepareParam(title, description, image, asList(tagList)); - - ItemData itemData = - new ItemData( - "123", - slug, - title, - description, - image, - false, - 0, - new DateTime(), - new DateTime(), - asList(tagList), - new ProfileData("userid", user.getUsername(), user.getBio(), user.getImage(), false)); - - when(itemQueryService.findBySlug(eq(Item.toSlug(title)), any())) - .thenReturn(Optional.of(itemData)); - - when(itemQueryService.findById(any(), any())).thenReturn(Optional.of(itemData)); - - given() - .contentType("application/json") - .header("Authorization", "Token " + token) - .body(param) - .when() - .post("/api/items") - .prettyPeek() - .then() - .statusCode(422); - } - - private HashMap prepareParam( - final String title, - final String description, - final String image, - final List tagList) { - return new HashMap() { - { - put( - "item", - new HashMap() { - { - put("title", title); - put("description", description); - put("image", image); - put("tagList", tagList); - } - }); - } - }; - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/ListItemApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/ListItemApiTest.java deleted file mode 100644 index 9f36d2c..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/ListItemApiTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static io.spring.TestHelper.itemDataFixture; -import static java.util.Arrays.asList; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.ItemQueryService; -import io.spring.application.Page; -import io.spring.application.data.ItemDataList; -import io.spring.application.item.ItemCommandService; -import io.spring.core.item.ItemRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest(ItemsApi.class) -@Import({WebSecurityConfig.class, JacksonCustomizations.class}) -public class ListItemApiTest extends TestWithCurrentUser { - @MockBean private ItemRepository itemRepository; - - @MockBean private ItemQueryService itemQueryService; - - @MockBean private ItemCommandService itemCommandService; - - @Autowired private MockMvc mvc; - - @Override - @BeforeEach - public void setUp() throws Exception { - super.setUp(); - RestAssuredMockMvc.mockMvc(mvc); - } - - @Test - public void should_get_default_item_list() throws Exception { - ItemDataList itemDataList = - new ItemDataList(asList(itemDataFixture("1", user), itemDataFixture("2", user)), 2); - when(itemQueryService.findRecentItems( - eq(null), eq(null), eq(null), eq(new Page(0, 20)), eq(null))) - .thenReturn(itemDataList); - RestAssuredMockMvc.when().get("/api/items").prettyPeek().then().statusCode(200); - } - - @Test - public void should_get_feeds_401_without_login() throws Exception { - RestAssuredMockMvc.when().get("/api/items/feed").prettyPeek().then().statusCode(401); - } - - @Test - public void should_get_feeds_success() throws Exception { - ItemDataList itemDataList = - new ItemDataList(asList(itemDataFixture("1", user), itemDataFixture("2", user)), 2); - when(itemQueryService.findUserFeed(eq(user), eq(new Page(0, 20)))).thenReturn(itemDataList); - - given() - .header("Authorization", "Token " + token) - .when() - .get("/api/items/feed") - .prettyPeek() - .then() - .statusCode(200); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/ProfileApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/ProfileApiTest.java deleted file mode 100644 index 2e3ab9c..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/ProfileApiTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.ProfileQueryService; -import io.spring.application.data.ProfileData; -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest(ProfileApi.class) -@Import({WebSecurityConfig.class, JacksonCustomizations.class}) -public class ProfileApiTest extends TestWithCurrentUser { - private User anotherUser; - - @Autowired private MockMvc mvc; - - @MockBean private ProfileQueryService profileQueryService; - - private ProfileData profileData; - - @BeforeEach - public void setUp() throws Exception { - super.setUp(); - RestAssuredMockMvc.mockMvc(mvc); - anotherUser = new User("username@test.com", "username", "123", "", ""); - profileData = - new ProfileData( - anotherUser.getId(), - anotherUser.getUsername(), - anotherUser.getBio(), - anotherUser.getImage(), - false); - when(userRepository.findByUsername(eq(anotherUser.getUsername()))) - .thenReturn(Optional.of(anotherUser)); - } - - @Test - public void should_get_user_profile_success() throws Exception { - when(profileQueryService.findByUsername(eq(profileData.getUsername()), eq(null))) - .thenReturn(Optional.of(profileData)); - RestAssuredMockMvc.when() - .get("/api/profiles/{username}", profileData.getUsername()) - .prettyPeek() - .then() - .statusCode(200) - .body("profile.username", equalTo(profileData.getUsername())); - } - - @Test - public void should_follow_user_success() throws Exception { - when(profileQueryService.findByUsername(eq(profileData.getUsername()), eq(user))) - .thenReturn(Optional.of(profileData)); - given() - .header("Authorization", "Token " + token) - .when() - .post("/api/profiles/{username}/follow", anotherUser.getUsername()) - .prettyPeek() - .then() - .statusCode(200); - verify(userRepository).saveRelation(new FollowRelation(user.getId(), anotherUser.getId())); - } - - @Test - public void should_unfollow_user_success() throws Exception { - FollowRelation followRelation = new FollowRelation(user.getId(), anotherUser.getId()); - when(userRepository.findRelation(eq(user.getId()), eq(anotherUser.getId()))) - .thenReturn(Optional.of(followRelation)); - when(profileQueryService.findByUsername(eq(profileData.getUsername()), eq(user))) - .thenReturn(Optional.of(profileData)); - - given() - .header("Authorization", "Token " + token) - .when() - .delete("/api/profiles/{username}/follow", anotherUser.getUsername()) - .prettyPeek() - .then() - .statusCode(200); - - verify(userRepository).removeRelation(eq(followRelation)); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/TestWithCurrentUser.java b/.framework/java/backend/src/test/java/io/spring/api/TestWithCurrentUser.java deleted file mode 100644 index 7d3b104..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/TestWithCurrentUser.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.spring.api; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import io.spring.application.data.UserData; -import io.spring.core.service.JwtService; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.mybatis.readservice.UserReadService; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.springframework.boot.test.mock.mockito.MockBean; - -abstract class TestWithCurrentUser { - @MockBean protected UserRepository userRepository; - - @MockBean protected UserReadService userReadService; - - protected User user; - protected UserData userData; - protected String token; - protected String email; - protected String username; - protected String defaultAvatar; - - @MockBean protected JwtService jwtService; - - protected void userFixture() { - email = "john@jacob.com"; - username = "johnjacob"; - defaultAvatar = "https://static.productionready.io/images/smiley-cyrus.jpg"; - - user = new User(email, username, "123", "", defaultAvatar); - when(userRepository.findByUsername(eq(username))).thenReturn(Optional.of(user)); - when(userRepository.findById(eq(user.getId()))).thenReturn(Optional.of(user)); - - userData = new UserData(user.getId(), email, username, "", defaultAvatar); - when(userReadService.findById(eq(user.getId()))).thenReturn(userData); - - token = "token"; - when(jwtService.getSubFromToken(eq(token))).thenReturn(Optional.of(user.getId())); - } - - @BeforeEach - public void setUp() throws Exception { - userFixture(); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/api/UsersApiTest.java b/.framework/java/backend/src/test/java/io/spring/api/UsersApiTest.java deleted file mode 100644 index 2eb3ba6..0000000 --- a/.framework/java/backend/src/test/java/io/spring/api/UsersApiTest.java +++ /dev/null @@ -1,271 +0,0 @@ -package io.spring.api; - -import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.restassured.module.mockmvc.RestAssuredMockMvc; -import io.spring.JacksonCustomizations; -import io.spring.api.security.WebSecurityConfig; -import io.spring.application.UserQueryService; -import io.spring.application.data.UserData; -import io.spring.application.user.UserService; -import io.spring.core.service.JwtService; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.mybatis.readservice.UserReadService; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.test.web.servlet.MockMvc; - -@WebMvcTest(UsersApi.class) -@Import({ - WebSecurityConfig.class, - UserQueryService.class, - BCryptPasswordEncoder.class, - JacksonCustomizations.class -}) -public class UsersApiTest { - @Autowired private MockMvc mvc; - - @MockBean private UserRepository userRepository; - - @MockBean private JwtService jwtService; - - @MockBean private UserReadService userReadService; - - @MockBean private UserService userService; - - @Autowired private PasswordEncoder passwordEncoder; - - private String defaultAvatar; - - @BeforeEach - public void setUp() throws Exception { - RestAssuredMockMvc.mockMvc(mvc); - defaultAvatar = "https://static.productionready.io/images/smiley-cyrus.jpg"; - } - - @Test - public void should_create_user_success() throws Exception { - String email = "john@jacob.com"; - String username = "johnjacob"; - - when(jwtService.toToken(any())).thenReturn("123"); - User user = new User(email, username, "123", "", defaultAvatar); - UserData userData = new UserData(user.getId(), email, username, "", defaultAvatar); - when(userReadService.findById(any())).thenReturn(userData); - - when(userService.createUser(any())).thenReturn(user); - - when(userRepository.findByUsername(eq(username))).thenReturn(Optional.empty()); - when(userRepository.findByEmail(eq(email))).thenReturn(Optional.empty()); - - Map param = prepareRegisterParameter(email, username); - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users") - .then() - .statusCode(201) - .body("user.email", equalTo(email)) - .body("user.username", equalTo(username)) - .body("user.bio", equalTo("")) - .body("user.image", equalTo(defaultAvatar)) - .body("user.token", equalTo("123")); - - verify(userService).createUser(any()); - } - - @Test - public void should_show_error_message_for_blank_username() throws Exception { - - String email = "john@jacob.com"; - String username = ""; - - Map param = prepareRegisterParameter(email, username); - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users") - .prettyPeek() - .then() - .statusCode(422) - .body("errors.username[0]", equalTo("can't be empty")); - } - - @Test - public void should_show_error_message_for_invalid_email() throws Exception { - String email = "johnxjacob.com"; - String username = "johnjacob"; - - Map param = prepareRegisterParameter(email, username); - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users") - .prettyPeek() - .then() - .statusCode(422) - .body("errors.email[0]", equalTo("should be an email")); - } - - @Test - public void should_show_error_for_duplicated_username() throws Exception { - String email = "john@jacob.com"; - String username = "johnjacob"; - - when(userRepository.findByUsername(eq(username))) - .thenReturn(Optional.of(new User(email, username, "123", "bio", ""))); - when(userRepository.findByEmail(any())).thenReturn(Optional.empty()); - - Map param = prepareRegisterParameter(email, username); - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users") - .prettyPeek() - .then() - .statusCode(422) - .body("errors.username[0]", equalTo("duplicated username")); - } - - @Test - public void should_show_error_for_duplicated_email() throws Exception { - String email = "john@jacob.com"; - String username = "johnjacob2"; - - when(userRepository.findByEmail(eq(email))) - .thenReturn(Optional.of(new User(email, username, "123", "bio", ""))); - - when(userRepository.findByUsername(eq(username))).thenReturn(Optional.empty()); - - Map param = prepareRegisterParameter(email, username); - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users") - .then() - .statusCode(422) - .body("errors.email[0]", equalTo("duplicated email")); - } - - private HashMap prepareRegisterParameter( - final String email, final String username) { - return new HashMap() { - { - put( - "user", - new HashMap() { - { - put("email", email); - put("password", "johnnyjacob"); - put("username", username); - } - }); - } - }; - } - - @Test - public void should_login_success() throws Exception { - String email = "john@jacob.com"; - String username = "johnjacob2"; - String password = "123"; - - User user = new User(email, username, passwordEncoder.encode(password), "", defaultAvatar); - UserData userData = new UserData("123", email, username, "", defaultAvatar); - - when(userRepository.findByEmail(eq(email))).thenReturn(Optional.of(user)); - when(userReadService.findByUsername(eq(username))).thenReturn(userData); - when(userReadService.findById(eq(user.getId()))).thenReturn(userData); - when(jwtService.toToken(any())).thenReturn("123"); - - Map param = - new HashMap() { - { - put( - "user", - new HashMap() { - { - put("email", email); - put("password", password); - } - }); - } - }; - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users/login") - .then() - .statusCode(200) - .body("user.email", equalTo(email)) - .body("user.username", equalTo(username)) - .body("user.bio", equalTo("")) - .body("user.image", equalTo(defaultAvatar)) - .body("user.token", equalTo("123")); - ; - } - - @Test - public void should_fail_login_with_wrong_password() throws Exception { - String email = "john@jacob.com"; - String username = "johnjacob2"; - String password = "123"; - - User user = new User(email, username, password, "", defaultAvatar); - UserData userData = new UserData(user.getId(), email, username, "", defaultAvatar); - - when(userRepository.findByEmail(eq(email))).thenReturn(Optional.of(user)); - when(userReadService.findByUsername(eq(username))).thenReturn(userData); - - Map param = - new HashMap() { - { - put( - "user", - new HashMap() { - { - put("email", email); - put("password", "123123"); - } - }); - } - }; - - given() - .contentType("application/json") - .body(param) - .when() - .post("/api/users/login") - .prettyPeek() - .then() - .statusCode(422) - .body("message", equalTo("invalid email or password")); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/application/comment/CommentQueryServiceTest.java b/.framework/java/backend/src/test/java/io/spring/application/comment/CommentQueryServiceTest.java deleted file mode 100644 index e36bc35..0000000 --- a/.framework/java/backend/src/test/java/io/spring/application/comment/CommentQueryServiceTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.spring.application.comment; - -import io.spring.application.CommentQueryService; -import io.spring.application.data.CommentData; -import io.spring.core.comment.Comment; -import io.spring.core.comment.CommentRepository; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisCommentRepository; -import io.spring.infrastructure.repository.MyBatisItemRepository; -import io.spring.infrastructure.repository.MyBatisUserRepository; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({ - MyBatisCommentRepository.class, - MyBatisUserRepository.class, - CommentQueryService.class, - MyBatisItemRepository.class -}) -public class CommentQueryServiceTest extends DbTestBase { - @Autowired private CommentRepository commentRepository; - - @Autowired private UserRepository userRepository; - - @Autowired private CommentQueryService commentQueryService; - - @Autowired private ItemRepository itemRepository; - - private User user; - - @BeforeEach - public void setUp() { - user = new User("aisensiy@test.com", "aisensiy", "123", "", ""); - userRepository.save(user); - } - - @Test - public void should_read_comment_success() { - Comment comment = new Comment("content", user.getId(), "123"); - commentRepository.save(comment); - - Optional optional = commentQueryService.findById(comment.getId(), user); - Assertions.assertTrue(optional.isPresent()); - CommentData commentData = optional.get(); - Assertions.assertEquals(commentData.getProfileData().getUsername(), user.getUsername()); - } - - @Test - public void should_read_comments_of_item() { - Item item = new Item("title", "desc", "image", Arrays.asList("java"), user.getId()); - itemRepository.save(item); - - User user2 = new User("user2@email.com", "user2", "123", "", ""); - userRepository.save(user2); - userRepository.saveRelation(new FollowRelation(user.getId(), user2.getId())); - - Comment comment1 = new Comment("content1", user.getId(), item.getId()); - commentRepository.save(comment1); - Comment comment2 = new Comment("content2", user2.getId(), item.getId()); - commentRepository.save(comment2); - - List comments = commentQueryService.findByItemId(item.getId(), user); - Assertions.assertEquals(comments.size(), 2); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/application/item/ItemQueryServiceTest.java b/.framework/java/backend/src/test/java/io/spring/application/item/ItemQueryServiceTest.java deleted file mode 100644 index 7338ea6..0000000 --- a/.framework/java/backend/src/test/java/io/spring/application/item/ItemQueryServiceTest.java +++ /dev/null @@ -1,226 +0,0 @@ -package io.spring.application.item; - -import io.spring.application.CursorPageParameter; -import io.spring.application.CursorPager; -import io.spring.application.CursorPager.Direction; -import io.spring.application.DateTimeCursor; -import io.spring.application.ItemQueryService; -import io.spring.application.Page; -import io.spring.application.data.ItemData; -import io.spring.application.data.ItemDataList; -import io.spring.core.favorite.ItemFavorite; -import io.spring.core.favorite.ItemFavoriteRepository; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisItemFavoriteRepository; -import io.spring.infrastructure.repository.MyBatisItemRepository; -import io.spring.infrastructure.repository.MyBatisUserRepository; -import java.util.Arrays; -import java.util.Optional; -import org.joda.time.DateTime; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({ - ItemQueryService.class, - MyBatisUserRepository.class, - MyBatisItemRepository.class, - MyBatisItemFavoriteRepository.class -}) -public class ItemQueryServiceTest extends DbTestBase { - @Autowired private ItemQueryService queryService; - - @Autowired private ItemRepository itemRepository; - - @Autowired private UserRepository userRepository; - - @Autowired private ItemFavoriteRepository itemFavoriteRepository; - - private User user; - private Item item; - - @BeforeEach - public void setUp() { - user = new User("aisensiy@gmail.com", "aisensiy", "123", "", ""); - userRepository.save(user); - item = - new Item( - "test", "desc", "image", Arrays.asList("java", "spring"), user.getId(), new DateTime()); - itemRepository.save(item); - } - - @Test - public void should_fetch_item_success() { - Optional optional = queryService.findById(item.getId(), user); - Assertions.assertTrue(optional.isPresent()); - - ItemData fetched = optional.get(); - Assertions.assertEquals(fetched.getFavoritesCount(), 0); - Assertions.assertFalse(fetched.isFavorited()); - Assertions.assertNotNull(fetched.getCreatedAt()); - Assertions.assertNotNull(fetched.getUpdatedAt()); - Assertions.assertTrue(fetched.getTagList().contains("java")); - } - - @Test - public void should_get_item_with_right_favorite_and_favorite_count() { - User anotherUser = new User("other@test.com", "other", "123", "", ""); - userRepository.save(anotherUser); - itemFavoriteRepository.save(new ItemFavorite(item.getId(), anotherUser.getId())); - - Optional optional = queryService.findById(item.getId(), anotherUser); - Assertions.assertTrue(optional.isPresent()); - - ItemData itemData = optional.get(); - Assertions.assertEquals(itemData.getFavoritesCount(), 1); - Assertions.assertTrue(itemData.isFavorited()); - } - - @Test - public void should_get_default_item_list() { - Item anotherItem = - new Item( - "new item", - "desc", - "image", - Arrays.asList("test"), - user.getId(), - new DateTime().minusHours(1)); - itemRepository.save(anotherItem); - - ItemDataList recentItems = queryService.findRecentItems(null, null, null, new Page(), user); - Assertions.assertEquals(recentItems.getCount(), 2); - Assertions.assertEquals(recentItems.getItemDatas().size(), 2); - Assertions.assertEquals(recentItems.getItemDatas().get(0).getId(), item.getId()); - - ItemDataList nodata = queryService.findRecentItems(null, null, null, new Page(2, 10), user); - Assertions.assertEquals(nodata.getCount(), 2); - Assertions.assertEquals(nodata.getItemDatas().size(), 0); - } - - @Test - public void should_get_default_item_list_by_cursor() { - Item anotherItem = - new Item( - "new item", - "desc", - "image", - Arrays.asList("test"), - user.getId(), - new DateTime().minusHours(1)); - itemRepository.save(anotherItem); - - CursorPager recentItems = - queryService.findRecentItemsWithCursor( - null, null, null, new CursorPageParameter<>(null, 20, Direction.NEXT), user); - Assertions.assertEquals(recentItems.getData().size(), 2); - Assertions.assertEquals(recentItems.getData().get(0).getId(), item.getId()); - - CursorPager nodata = - queryService.findRecentItemsWithCursor( - null, - null, - null, - new CursorPageParameter( - DateTimeCursor.parse(recentItems.getEndCursor().toString()), 20, Direction.NEXT), - user); - Assertions.assertEquals(nodata.getData().size(), 0); - Assertions.assertEquals(nodata.getStartCursor(), null); - - CursorPager prevItems = - queryService.findRecentItemsWithCursor( - null, null, null, new CursorPageParameter<>(null, 20, Direction.PREV), user); - Assertions.assertEquals(prevItems.getData().size(), 2); - } - - @Test - public void should_query_item_by_seller() { - User anotherUser = new User("other@email.com", "other", "123", "", ""); - userRepository.save(anotherUser); - - Item anotherItem = - new Item("new item", "desc", "image", Arrays.asList("test"), anotherUser.getId()); - itemRepository.save(anotherItem); - - ItemDataList recentItems = - queryService.findRecentItems(null, user.getUsername(), null, new Page(), user); - Assertions.assertEquals(recentItems.getItemDatas().size(), 1); - Assertions.assertEquals(recentItems.getCount(), 1); - } - - @Test - public void should_query_item_by_favorite() { - User anotherUser = new User("other@email.com", "other", "123", "", ""); - userRepository.save(anotherUser); - - Item anotherItem = - new Item("new item", "desc", "image", Arrays.asList("test"), anotherUser.getId()); - itemRepository.save(anotherItem); - - ItemFavorite itemFavorite = new ItemFavorite(item.getId(), anotherUser.getId()); - itemFavoriteRepository.save(itemFavorite); - - ItemDataList recentItems = - queryService.findRecentItems( - null, null, anotherUser.getUsername(), new Page(), anotherUser); - Assertions.assertEquals(recentItems.getItemDatas().size(), 1); - Assertions.assertEquals(recentItems.getCount(), 1); - ItemData itemData = recentItems.getItemDatas().get(0); - Assertions.assertEquals(itemData.getId(), item.getId()); - Assertions.assertEquals(itemData.getFavoritesCount(), 1); - Assertions.assertTrue(itemData.isFavorited()); - } - - @Test - public void should_query_item_by_tag() { - Item anotherItem = new Item("new item", "desc", "image", Arrays.asList("test"), user.getId()); - itemRepository.save(anotherItem); - - ItemDataList recentItems = queryService.findRecentItems("spring", null, null, new Page(), user); - Assertions.assertEquals(recentItems.getItemDatas().size(), 1); - Assertions.assertEquals(recentItems.getCount(), 1); - Assertions.assertEquals(recentItems.getItemDatas().get(0).getId(), item.getId()); - - ItemDataList notag = queryService.findRecentItems("notag", null, null, new Page(), user); - Assertions.assertEquals(notag.getCount(), 0); - } - - @Test - public void should_show_following_if_user_followed_seller() { - User anotherUser = new User("other@email.com", "other", "123", "", ""); - userRepository.save(anotherUser); - - FollowRelation followRelation = new FollowRelation(anotherUser.getId(), user.getId()); - userRepository.saveRelation(followRelation); - - ItemDataList recentItems = - queryService.findRecentItems(null, null, null, new Page(), anotherUser); - Assertions.assertEquals(recentItems.getCount(), 1); - ItemData itemData = recentItems.getItemDatas().get(0); - Assertions.assertTrue(itemData.getProfileData().isFollowing()); - } - - @Test - public void should_get_user_feed() { - User anotherUser = new User("other@email.com", "other", "123", "", ""); - userRepository.save(anotherUser); - - FollowRelation followRelation = new FollowRelation(anotherUser.getId(), user.getId()); - userRepository.saveRelation(followRelation); - - ItemDataList userFeed = queryService.findUserFeed(user, new Page()); - Assertions.assertEquals(userFeed.getCount(), 0); - - ItemDataList anotherUserFeed = queryService.findUserFeed(anotherUser, new Page()); - Assertions.assertEquals(anotherUserFeed.getCount(), 1); - ItemData itemData = anotherUserFeed.getItemDatas().get(0); - Assertions.assertTrue(itemData.getProfileData().isFollowing()); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/application/profile/ProfileQueryServiceTest.java b/.framework/java/backend/src/test/java/io/spring/application/profile/ProfileQueryServiceTest.java deleted file mode 100644 index 34ce502..0000000 --- a/.framework/java/backend/src/test/java/io/spring/application/profile/ProfileQueryServiceTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.spring.application.profile; - -import io.spring.application.ProfileQueryService; -import io.spring.application.data.ProfileData; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisUserRepository; -import java.util.Optional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({ProfileQueryService.class, MyBatisUserRepository.class}) -public class ProfileQueryServiceTest extends DbTestBase { - @Autowired private ProfileQueryService profileQueryService; - @Autowired private UserRepository userRepository; - - @Test - public void should_fetch_profile_success() { - User currentUser = new User("a@test.com", "a", "123", "", ""); - User profileUser = new User("p@test.com", "p", "123", "", ""); - userRepository.save(profileUser); - - Optional optional = - profileQueryService.findByUsername(profileUser.getUsername(), currentUser); - Assertions.assertTrue(optional.isPresent()); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/application/tag/TagsQueryServiceTest.java b/.framework/java/backend/src/test/java/io/spring/application/tag/TagsQueryServiceTest.java deleted file mode 100644 index 084cae8..0000000 --- a/.framework/java/backend/src/test/java/io/spring/application/tag/TagsQueryServiceTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.spring.application.tag; - -import io.spring.application.TagsQueryService; -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisItemRepository; -import java.util.Arrays; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({TagsQueryService.class, MyBatisItemRepository.class}) -public class TagsQueryServiceTest extends DbTestBase { - @Autowired private TagsQueryService tagsQueryService; - - @Autowired private ItemRepository itemRepository; - - @Test - public void should_get_all_tags() { - itemRepository.save(new Item("test", "test", "image", Arrays.asList("java"), "123")); - Assertions.assertTrue(tagsQueryService.allTags().contains("java")); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/core/item/ItemTest.java b/.framework/java/backend/src/test/java/io/spring/core/item/ItemTest.java deleted file mode 100644 index e7cdd5c..0000000 --- a/.framework/java/backend/src/test/java/io/spring/core/item/ItemTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.spring.core.item; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import java.util.Arrays; -import org.junit.jupiter.api.Test; - -public class ItemTest { - - @Test - public void should_get_right_slug() { - Item item = new Item("a new title", "desc", "image", Arrays.asList("java"), "123"); - assertThat(item.getSlug(), is("a-new-title")); - } - - @Test - public void should_get_right_slug_with_number_in_title() { - Item item = new Item("a new title 2", "desc", "image", Arrays.asList("java"), "123"); - assertThat(item.getSlug(), is("a-new-title-2")); - } - - @Test - public void should_get_lower_case_slug() { - Item item = new Item("A NEW TITLE", "desc", "image", Arrays.asList("java"), "123"); - assertThat(item.getSlug(), is("a-new-title")); - } - - @Test - public void should_handle_other_language() { - Item item = new Item("中文:标题", "desc", "image", Arrays.asList("java"), "123"); - assertThat(item.getSlug(), is("中文-标题")); - } - - @Test - public void should_handle_commas() { - Item item = new Item("what?the.hell,w", "desc", "image", Arrays.asList("java"), "123"); - assertThat(item.getSlug(), is("what-the-hell-w")); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/DbTestBase.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/DbTestBase.java deleted file mode 100644 index 80ed81c..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/DbTestBase.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.spring.infrastructure; - -import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace; -import org.springframework.test.context.ActiveProfiles; - -@ActiveProfiles("test") -@AutoConfigureTestDatabase(replace = Replace.NONE) -@MybatisTest -public abstract class DbTestBase {} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/comment/MyBatisCommentRepositoryTest.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/comment/MyBatisCommentRepositoryTest.java deleted file mode 100644 index 8cc9a66..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/comment/MyBatisCommentRepositoryTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.spring.infrastructure.comment; - -import io.spring.core.comment.Comment; -import io.spring.core.comment.CommentRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisCommentRepository; -import java.util.Optional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({MyBatisCommentRepository.class}) -public class MyBatisCommentRepositoryTest extends DbTestBase { - @Autowired private CommentRepository commentRepository; - - @Test - public void should_create_and_fetch_comment_success() { - Comment comment = new Comment("content", "123", "456"); - commentRepository.save(comment); - - Optional optional = commentRepository.findById("456", comment.getId()); - Assertions.assertTrue(optional.isPresent()); - Assertions.assertEquals(optional.get(), comment); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/favorite/MyBatisItemFavoriteRepositoryTest.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/favorite/MyBatisItemFavoriteRepositoryTest.java deleted file mode 100644 index d94e73f..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/favorite/MyBatisItemFavoriteRepositoryTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.spring.infrastructure.favorite; - -import io.spring.core.favorite.ItemFavorite; -import io.spring.core.favorite.ItemFavoriteRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisItemFavoriteRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({MyBatisItemFavoriteRepository.class}) -public class MyBatisItemFavoriteRepositoryTest extends DbTestBase { - @Autowired private ItemFavoriteRepository itemFavoriteRepository; - - @Autowired private io.spring.infrastructure.mybatis.mapper.ItemFavoriteMapper itemFavoriteMapper; - - @Test - public void should_save_and_fetch_itemFavorite_success() { - ItemFavorite itemFavorite = new ItemFavorite("123", "456"); - itemFavoriteRepository.save(itemFavorite); - Assertions.assertNotNull( - itemFavoriteMapper.find(itemFavorite.getItemId(), itemFavorite.getUserId())); - } - - @Test - public void should_remove_favorite_success() { - ItemFavorite itemFavorite = new ItemFavorite("123", "456"); - itemFavoriteRepository.save(itemFavorite); - itemFavoriteRepository.remove(itemFavorite); - Assertions.assertFalse(itemFavoriteRepository.find("123", "456").isPresent()); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/item/ItemRepositoryTransactionTest.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/item/ItemRepositoryTransactionTest.java deleted file mode 100644 index 63c441e..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/item/ItemRepositoryTransactionTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.spring.infrastructure.item; - -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.mybatis.mapper.ItemMapper; -import java.util.Arrays; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; - -@ActiveProfiles("test") -@SpringBootTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -public class ItemRepositoryTransactionTest { - @Autowired private ItemRepository itemRepository; - - @Autowired private UserRepository userRepository; - - @Autowired private ItemMapper itemMapper; - - @Test - public void transactional_test() { - User user = new User("aisensiy@gmail.com", "aisensiy", "123", "bio", "default"); - userRepository.save(user); - Item item = new Item("test", "desc", "image", Arrays.asList("java", "spring"), user.getId()); - itemRepository.save(item); - Item anotherItem = - new Item("test", "desc", "image", Arrays.asList("java", "spring", "other"), user.getId()); - try { - itemRepository.save(anotherItem); - } catch (Exception e) { - Assertions.assertNull(itemMapper.findTag("other")); - } - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/item/MyBatisItemRepositoryTest.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/item/MyBatisItemRepositoryTest.java deleted file mode 100644 index 8bdc808..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/item/MyBatisItemRepositoryTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.spring.infrastructure.item; - -import io.spring.core.item.Item; -import io.spring.core.item.ItemRepository; -import io.spring.core.item.Tag; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisItemRepository; -import io.spring.infrastructure.repository.MyBatisUserRepository; -import java.util.Arrays; -import java.util.Optional; -import java.util.Random; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import({MyBatisItemRepository.class, MyBatisUserRepository.class}) -public class MyBatisItemRepositoryTest extends DbTestBase { - @Autowired private ItemRepository itemRepository; - - @Autowired private UserRepository userRepository; - - private Item item; - - @BeforeEach - public void setUp() { - Random random = new Random(); - int randomNumber = random.nextInt(); - User user = - new User( - "aisensiy" + randomNumber + "@gmail.com", "aisensiy" + randomNumber, "123", "", ""); - userRepository.save(user); - item = - new Item( - "test-" + randomNumber, "desc", "image", Arrays.asList("java", "spring"), user.getId()); - } - - @Test - public void should_create_and_fetch_item_success() { - itemRepository.save(item); - Optional optional = itemRepository.findById(item.getId()); - Assertions.assertTrue(optional.isPresent()); - Assertions.assertEquals(optional.get(), item); - Assertions.assertTrue(optional.get().getTags().contains(new Tag("java"))); - Assertions.assertTrue(optional.get().getTags().contains(new Tag("spring"))); - } - - @Test - public void should_update_and_fetch_item_success() { - itemRepository.save(item); - - String newTitle = "new test 2"; - item.update(newTitle, "", ""); - itemRepository.save(item); - System.out.println(item.getSlug()); - Optional optional = itemRepository.findBySlug(item.getSlug()); - Assertions.assertTrue(optional.isPresent()); - Item fetched = optional.get(); - Assertions.assertEquals(fetched.getTitle(), newTitle); - } - - @Test - public void should_delete_item() { - itemRepository.save(item); - - itemRepository.remove(item); - Assertions.assertFalse(itemRepository.findById(item.getId()).isPresent()); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/service/DefaultJwtServiceTest.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/service/DefaultJwtServiceTest.java deleted file mode 100644 index b226170..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/service/DefaultJwtServiceTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.spring.infrastructure.service; - -import io.spring.core.service.JwtService; -import io.spring.core.user.User; -import java.util.Optional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class DefaultJwtServiceTest { - - private JwtService jwtService; - - @BeforeEach - public void setUp() { - jwtService = - new DefaultJwtService("123123123123123123123123123123123123123123123123123123123123", 3600); - } - - @Test - public void should_generate_and_parse_token() { - User user = new User("email@email.com", "username", "123", "", ""); - String token = jwtService.toToken(user); - Assertions.assertNotNull(token); - Optional optional = jwtService.getSubFromToken(token); - Assertions.assertTrue(optional.isPresent()); - Assertions.assertEquals(optional.get(), user.getId()); - } - - @Test - public void should_get_null_with_wrong_jwt() { - Optional optional = jwtService.getSubFromToken("123"); - Assertions.assertFalse(optional.isPresent()); - } - - @Test - public void should_get_null_with_expired_jwt() { - String token = - "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhaXNlbnNpeSIsImV4cCI6MTUwMjE2MTIwNH0.SJB-U60WzxLYNomqLo4G3v3LzFxJKuVrIud8D8Lz3-mgpo9pN1i7C8ikU_jQPJGm8HsC1CquGMI-rSuM7j6LDA"; - Assertions.assertFalse(jwtService.getSubFromToken(token).isPresent()); - } -} diff --git a/.framework/java/backend/src/test/java/io/spring/infrastructure/user/MyBatisUserRepositoryTest.java b/.framework/java/backend/src/test/java/io/spring/infrastructure/user/MyBatisUserRepositoryTest.java deleted file mode 100644 index 8d4aaa2..0000000 --- a/.framework/java/backend/src/test/java/io/spring/infrastructure/user/MyBatisUserRepositoryTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.spring.infrastructure.user; - -import io.spring.core.user.FollowRelation; -import io.spring.core.user.User; -import io.spring.core.user.UserRepository; -import io.spring.infrastructure.DbTestBase; -import io.spring.infrastructure.repository.MyBatisUserRepository; -import java.util.Optional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -@Import(MyBatisUserRepository.class) -public class MyBatisUserRepositoryTest extends DbTestBase { - @Autowired private UserRepository userRepository; - private User user; - - @BeforeEach - public void setUp() { - user = new User("aisensiy@16322.com", "aisensiy999", "1234", "", ""); - } - - @Test - public void should_save_and_fetch_user_success() { - userRepository.save(user); - Optional userOptional = userRepository.findByUsername("aisensiy999"); - Assertions.assertEquals(userOptional.get(), user); - Optional userOptional2 = userRepository.findByEmail("aisensiy@16322.com"); - Assertions.assertEquals(userOptional2.get(), user); - } - - @Test - public void should_update_user_success() { - String newEmail = "newemail@email.com"; - user.update(newEmail, "aa", "bb", "cc", "dd"); - userRepository.save(user); - Optional optional = userRepository.findByUsername(user.getUsername()); - Assertions.assertTrue(optional.isPresent()); - Assertions.assertEquals(optional.get().getEmail(), newEmail); - - String newUsername = "newUsername"; - user.update("", newUsername, "", "", ""); - userRepository.save(user); - optional = userRepository.findByEmail(user.getEmail()); - Assertions.assertTrue(optional.isPresent()); - Assertions.assertEquals(optional.get().getUsername(), newUsername); - Assertions.assertEquals(optional.get().getImage(), user.getImage()); - } - - @Test - public void should_create_new_user_follow_success() { - User other = new User("other@example.com", "other", "123", "", ""); - userRepository.save(other); - - FollowRelation followRelation = new FollowRelation(user.getId(), other.getId()); - userRepository.saveRelation(followRelation); - Assertions.assertTrue(userRepository.findRelation(user.getId(), other.getId()).isPresent()); - } - - @Test - public void should_unfollow_user_success() { - User other = new User("other@example.com", "other", "123", "", ""); - userRepository.save(other); - - FollowRelation followRelation = new FollowRelation(user.getId(), other.getId()); - userRepository.saveRelation(followRelation); - - userRepository.removeRelation(followRelation); - Assertions.assertFalse(userRepository.findRelation(user.getId(), other.getId()).isPresent()); - } -} diff --git a/.framework/java/backend/start.sh b/.framework/java/backend/start.sh deleted file mode 100755 index b405727..0000000 --- a/.framework/java/backend/start.sh +++ /dev/null @@ -1,6 +0,0 @@ -./gradlew -i bootRun & - -while true; do - inotifywait -e modify,create,delete,move -r ./src/ && \ - ./gradlew -i assemble -done diff --git a/.framework/java/charts/templates/anythink-backend-deployment.yaml b/.framework/java/charts/templates/anythink-backend-deployment.yaml deleted file mode 100644 index 7b209f5..0000000 --- a/.framework/java/charts/templates/anythink-backend-deployment.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.backend.serviceName }} - name: {{ .Values.backend.serviceName }} -spec: - replicas: {{ .Values.backend.replicaCount }} - selector: - matchLabels: - app: {{ .Values.backend.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.backend.serviceName }} - date: {{ now | unixEpoch | quote }} - spec: - containers: - - args: - - sh - - -c - - "gradlew bootRun" - env: - - name: APP_ENV - value: dev - - name: SECRET_KEY - value: secret - - name: DEBUG - value: "True" - - name: DATABASE_URL - value: "{{ .Values.database.connectionProtocol }}{{ .Values.database.env.password }}:@{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}/{{ .Values.database.databaseName }}" - image: "{{ include "anythink-tenant.backendRepository" .}}:{{ .Values.backend.image.tag }}" - imagePullPolicy: {{ .Values.backend.image.pullPolicy }} - name: {{ .Values.backend.serviceName }} - ports: - - containerPort: {{ .Values.backend.containerPort }} - name: http - protocol: TCP - startupProbe: - httpGet: - path: /health - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: /health - port: http - readinessProbe: - httpGet: - path: /health - port: http - resources: - {{- toYaml .Values.backend.resources | nindent 12 }} - initContainers: - env: - - name: APP_ENV - value: dev - - name: SECRET_KEY - value: secret - - name: DEBUG - value: "True" - - name: DATABASE_URL - value: "{{ .Values.database.connectionProtocol}}{{ .Values.database.env.password}}:@{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}/{{ .Values.database.databaseName }}" - image: "{{ include "anythink-tenant.backendRepository" .}}:{{ .Values.backend.image.tag }}" - imagePullPolicy: {{ .Values.backend.image.pullPolicy }} - name: db-migrations - restartPolicy: Always diff --git a/.framework/java/charts/templates/database-deployment.yaml b/.framework/java/charts/templates/database-deployment.yaml deleted file mode 100644 index 19752ee..0000000 --- a/.framework/java/charts/templates/database-deployment.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if .Values.database.deploy }} -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.database.serviceName }} - name: {{ .Values.database.serviceName }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.database.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.database.serviceName }} - spec: - containers: - - image: "{{ .Values.database.image.repository }}:{{ .Values.database.image.tag }}" - name: {{ .Values.database.serviceName }} - env: - - name: POSTGRES_HOST_AUTH_METHOD - value: trust - - name: POSTGRES_USER - value: {{ .Values.database.env.userName }} - - name: POSTGRES_PASSWORD - value: {{ .Values.database.env.password }} - - name: POSTGRES_DB - value: {{ .Values.database.databaseName }} - imagePullPolicy: {{ .Values.database.image.pullPolicy }} - ports: - - containerPort: {{ .Values.database.containerPort }} - resources: {} - volumeMounts: - - mountPath: /data/db - name: {{ .Values.database.serviceName }}-0 - restartPolicy: Always - volumes: - - name: {{ .Values.database.serviceName }}-0 - persistentVolumeClaim: - claimName: {{ .Values.database.serviceName }}-0 -{{- end }} diff --git a/.framework/java/charts/values.yaml b/.framework/java/charts/values.yaml deleted file mode 100644 index 0464a04..0000000 --- a/.framework/java/charts/values.yaml +++ /dev/null @@ -1,70 +0,0 @@ -clusterEnv: "" -productionBackendHost: "prod.anythink.market" -stagingBackendHost: "staging.anythink.market" - -backend: - serviceName: anythink-backend - containerPort: 3000 - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/anythink-backend - stagingRepository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/staging-anythink-backend - pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 128Mi - -frontend: - serviceName: anythink-frontend - containerPort: 3001 - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/anythink-frontend - stagingRepository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/staging-anythink-frontend - pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - resources: - limits: - cpu: 600m - memory: 768Mi - requests: - cpu: 100m - memory: 128Mi - -database: - deploy: true - connectionProtocol: postgresql:// - serviceName: postgres-python - containerPort: 5433 - servicePort: 5432 - databaseName: anythink-market - replicaCount: 1 - env: - password: postgres - service: - type: ClusterIP - port: 80 - image: - repository: postgres - pullPolicy: IfNotPresent - tag: "latest" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi diff --git a/.framework/java/docker-compose.yml b/.framework/java/docker-compose.yml deleted file mode 100644 index 17f2aad..0000000 --- a/.framework/java/docker-compose.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: "3.8" -services: - anythink-backend-java: - build: ./backend - container_name: anythink-backend-java - command: sh -c "cd backend && /wait-for-it.sh postgres-java:5432 -q -t 60 && ./start.sh" - - environment: - - PORT=3000 - - GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN=${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN} - working_dir: /usr/src - volumes: - - ./:/usr/src/ - - /usr/src/backend/node_modules - ports: - - "3000:3000" - depends_on: - - "postgres-java" - - anythink-frontend-react: - build: ./frontend - container_name: anythink-frontend-react - command: sh -c "cd frontend && yarn install && /wait-for-it.sh anythink-backend-java:3000 -t 120 --strict -- curl --head -X GET --retry 30 --retry-connrefused --retry-delay 1 anythink-backend-java:3000/api/ping && yarn start" - environment: - - NODE_ENV=development - - PORT=3001 - - REACT_APP_BACKEND_URL=${CODESPACE_BACKEND_URL:-http://localhost:3000} - - WDS_SOCKET_PORT=${CODESPACE_WDS_SOCKET_PORT:-3001} - working_dir: /usr/src - volumes: - - ./:/usr/src/ - - /usr/src/frontend/node_modules - ports: - - "3001:3001" - depends_on: - - "anythink-backend-java" - - postgres-java: - container_name: postgres-java - restart: on-failure - image: postgres - logging: - driver: none - environment: - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PASSWORD: postgres - POSTGRES_DB: anythink-market - volumes: - - ~/postgres/data:/data/db - ports: - - '5433:5432' - - anythink-ack: - image: public.ecr.aws/v0a2l7y2/wilco/anythink-ack:latest - container_name: anythink-ack - environment: - - GITHUB_TOKEN=$GITHUB_TOKEN - - CODESPACE_NAME=$CODESPACE_NAME - depends_on: - - "anythink-frontend-react" diff --git a/.framework/node/backend/.gitignore b/.framework/node/backend/.gitignore deleted file mode 100644 index a812403..0000000 --- a/.framework/node/backend/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# Logs -logs -*.log -.DS_Store - -npm-debug.log* - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directory -node_modules - -# Optional npm cache directory -.npm - -# Optional REPL history -.node_repl_history - -.idea diff --git a/.framework/node/backend/Dockerfile b/.framework/node/backend/Dockerfile deleted file mode 100644 index e779cce..0000000 --- a/.framework/node/backend/Dockerfile +++ /dev/null @@ -1 +0,0 @@ -FROM public.ecr.aws/v0a2l7y2/wilco/anythink-backend-node:latest diff --git a/.framework/node/backend/Dockerfile.aws b/.framework/node/backend/Dockerfile.aws deleted file mode 100644 index 7ce8e4a..0000000 --- a/.framework/node/backend/Dockerfile.aws +++ /dev/null @@ -1,10 +0,0 @@ -FROM node:16 - -WORKDIR /usr/src -COPY backend ./backend -COPY .wilco ./.wilco - -# Pre-install npm packages -WORKDIR /usr/src/backend -RUN yarn install - diff --git a/.framework/node/backend/README.md b/.framework/node/backend/README.md deleted file mode 100644 index 14f890a..0000000 --- a/.framework/node/backend/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Anythink Market Backend - -The Anythink Market backend is Node web app written with [Express](https://expressjs.com/) - -## Dependencies - -- [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) - For generating JWTs used by authentication -- [mongoose](https://github.com/Automattic/mongoose) - For modeling and mapping MongoDB data to javascript -- [mongoose-unique-validator](https://github.com/blakehaswell/mongoose-unique-validator) - For handling unique validation errors in Mongoose. Mongoose only handles validation at the document level, so a unique index across a collection will throw an exception at the driver level. The `mongoose-unique-validator` plugin helps us by formatting the error like a normal mongoose `ValidationError`. -- [passport](https://github.com/jaredhanson/passport) - For handling user authentication -- [slug](https://github.com/dodo/node-slug) - For encoding titles into a URL-friendly format - -## Application Structure - -- `app.js` - The entry point to our application. This file defines our express server and connects it to MongoDB using mongoose. It also requires the routes and models we'll be using in the application. -- `config/` - This folder contains configuration for passport as well as a central location for configuration/environment variables. -- `routes/` - This folder contains the route definitions for our API. -- `models/` - This folder contains the schema definitions for our Mongoose models. - -## Error Handling - -In `routes/api/index.js`, we define a error-handling middleware for handling Mongoose's `ValidationError`. This middleware will respond with a 422 status code and format the response to have [error messages the clients can understand](https://github.com/gothinkster/realworld/blob/master/API.md#errors-and-status-codes) diff --git a/.framework/node/backend/app.js b/.framework/node/backend/app.js deleted file mode 100644 index f4e7f35..0000000 --- a/.framework/node/backend/app.js +++ /dev/null @@ -1,89 +0,0 @@ -require("dotenv").config(); -var http = require("http"), - path = require("path"), - methods = require("methods"), - express = require("express"), - bodyParser = require("body-parser"), - session = require("express-session"), - cors = require("cors"), - passport = require("passport"), - errorhandler = require("errorhandler"), - mongoose = require("mongoose"); - -var isProduction = process.env.NODE_ENV === "production"; - -// Create global app object -var app = express(); - -app.use(cors()); - -// Normal express config defaults -app.use(require("morgan")("dev")); -app.use(bodyParser.urlencoded({ extended: false })); -app.use(bodyParser.json()); - -app.use(require("method-override")()); -app.use(express.static(__dirname + "/public")); - -app.use( - session({ - secret: "secret", - cookie: { maxAge: 60000 }, - resave: false, - saveUninitialized: false - }) -); - -if (!isProduction) { - app.use(errorhandler()); -} - -if (!process.env.MONGODB_URI) { - console.warn("Missing MONGODB_URI in env, please add it to your .env file"); -} - -mongoose.connect(process.env.MONGODB_URI); -if (isProduction) { -} else { - mongoose.set("debug", true); -} - -require("./models/User"); -require("./models/Item"); -require("./models/Comment"); -require("./config/passport"); - -app.use(require("./routes")); - -/// catch 404 and forward to error handler -app.use(function (req, res, next) { - if (req.url === "/favicon.ico") { - res.writeHead(200, { "Content-Type": "image/x-icon" }); - res.end(); - } else { - const err = new Error("Not Found"); - err.status = 404; - next(err); - } -}); - -/// error handler -app.use(function(err, req, res, next) { - console.log(err.stack); - if (isProduction) { - res.sendStatus(err.status || 500) - } else { - res.status(err.status || 500); - res.json({ - errors: { - message: err.message, - error: err - } - }); - } -}); - -// finally, let's start our server... -var server = app.listen(process.env.PORT || 3000, function() { - console.log("Listening on port " + server.address().port); -}); diff --git a/.framework/node/backend/config/index.js b/.framework/node/backend/config/index.js deleted file mode 100644 index 1bf9d6a..0000000 --- a/.framework/node/backend/config/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - secret: process.env.NODE_ENV === 'production' ? process.env.SECRET : 'secret' -}; diff --git a/.framework/node/backend/config/passport.js b/.framework/node/backend/config/passport.js deleted file mode 100644 index abe0ce2..0000000 --- a/.framework/node/backend/config/passport.js +++ /dev/null @@ -1,18 +0,0 @@ -var passport = require('passport'); -var LocalStrategy = require('passport-local').Strategy; -var mongoose = require('mongoose'); -var User = mongoose.model('User'); - -passport.use(new LocalStrategy({ - usernameField: 'user[email]', - passwordField: 'user[password]' -}, function(email, password, done) { - User.findOne({email: email}).then(function(user){ - if(!user || !user.validPassword(password)){ - return done(null, false, {errors: {'email or password': 'is invalid'}}); - } - - return done(null, user); - }).catch(done); -})); - diff --git a/.framework/node/backend/lib/event.js b/.framework/node/backend/lib/event.js deleted file mode 100644 index 48a270e..0000000 --- a/.framework/node/backend/lib/event.js +++ /dev/null @@ -1,25 +0,0 @@ -const axiosLib = require("axios"); -const fs = require("fs"); - -const WILCO_ID = process.env.WILCO_ID || fs.readFileSync('../.wilco', 'utf8') -const baseURL = process.env.ENGINE_BASE_URL || "https://engine.wilco.gg" - -const axios = axiosLib.create({ - baseURL: baseURL, - headers: { - 'Content-type': 'application/json', - }, -}); - -async function sendEvent(event, metadata) { - try { - const result = await axios.post(`/users/${WILCO_ID}/event`, JSON.stringify({event, metadata})); - return result.data; - } catch (error) { - console.error(`failed to send event ${event} to Wilco engine`) - } -} - -module.exports = { - sendEvent, -} diff --git a/.framework/node/backend/models/Comment.js b/.framework/node/backend/models/Comment.js deleted file mode 100644 index 995c6c0..0000000 --- a/.framework/node/backend/models/Comment.js +++ /dev/null @@ -1,22 +0,0 @@ -var mongoose = require("mongoose"); - -var CommentSchema = new mongoose.Schema( - { - body: String, - seller: { type: mongoose.Schema.Types.ObjectId, ref: "User" }, - item: { type: mongoose.Schema.Types.ObjectId, ref: "Item" } - }, - { timestamps: true } -); - -// Requires population of seller -CommentSchema.methods.toJSONFor = function(user) { - return { - id: this._id, - body: this.body, - createdAt: this.createdAt, - seller: this.seller.toProfileJSONFor(user) - }; -}; - -mongoose.model("Comment", CommentSchema); diff --git a/.framework/node/backend/models/Item.js b/.framework/node/backend/models/Item.js deleted file mode 100644 index 96421a3..0000000 --- a/.framework/node/backend/models/Item.js +++ /dev/null @@ -1,62 +0,0 @@ -var mongoose = require("mongoose"); -var uniqueValidator = require("mongoose-unique-validator"); -var slug = require("slug"); -var User = mongoose.model("User"); - -var ItemSchema = new mongoose.Schema( - { - slug: { type: String, lowercase: true, unique: true }, - title: {type: String, required: [true, "can't be blank"]}, - description: {type: String, required: [true, "can't be blank"]}, - image: String, - favoritesCount: { type: Number, default: 0 }, - comments: [{ type: mongoose.Schema.Types.ObjectId, ref: "Comment" }], - tagList: [{ type: String }], - seller: { type: mongoose.Schema.Types.ObjectId, ref: "User" } - }, - { timestamps: true } -); - -ItemSchema.plugin(uniqueValidator, { message: "is already taken" }); - -ItemSchema.pre("validate", function(next) { - if (!this.slug) { - this.slugify(); - } - - next(); -}); - -ItemSchema.methods.slugify = function() { - this.slug = - slug(this.title) + - "-" + - ((Math.random() * Math.pow(36, 6)) | 0).toString(36); -}; - -ItemSchema.methods.updateFavoriteCount = function() { - var item = this; - - return User.count({ favorites: { $in: [item._id] } }).then(function(count) { - item.favoritesCount = count; - - return item.save(); - }); -}; - -ItemSchema.methods.toJSONFor = function(user) { - return { - slug: this.slug, - title: this.title, - description: this.description, - image: this.image, - createdAt: this.createdAt, - updatedAt: this.updatedAt, - tagList: this.tagList, - favorited: user ? user.isFavorite(this._id) : false, - favoritesCount: this.favoritesCount, - seller: this.seller.toProfileJSONFor(user) - }; -}; - -mongoose.model("Item", ItemSchema); diff --git a/.framework/node/backend/models/User.js b/.framework/node/backend/models/User.js deleted file mode 100644 index 8616f03..0000000 --- a/.framework/node/backend/models/User.js +++ /dev/null @@ -1,130 +0,0 @@ -var mongoose = require("mongoose"); -var uniqueValidator = require("mongoose-unique-validator"); -var crypto = require("crypto"); -var jwt = require("jsonwebtoken"); -var secret = require("../config").secret; - -var UserSchema = new mongoose.Schema( - { - username: { - type: String, - lowercase: true, - unique: true, - required: [true, "can't be blank"], - match: [/^[a-zA-Z0-9]+$/, "is invalid"], - index: true - }, - email: { - type: String, - lowercase: true, - unique: true, - required: [true, "can't be blank"], - match: [/\S+@\S+\.\S+/, "is invalid"], - index: true - }, - bio: String, - image: String, - role: { - type: String, - enum: ["user", "admin"], - default: "user" - }, - favorites: [{ type: mongoose.Schema.Types.ObjectId, ref: "Item" }], - following: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }], - hash: String, - salt: String - }, - { timestamps: true } -); - -UserSchema.plugin(uniqueValidator, { message: "is already taken." }); - -UserSchema.methods.validPassword = function(password) { - var hash = crypto - .pbkdf2Sync(password, this.salt, 10000, 512, "sha512") - .toString("hex"); - return this.hash === hash; -}; - -UserSchema.methods.setPassword = function(password) { - this.salt = crypto.randomBytes(16).toString("hex"); - this.hash = crypto - .pbkdf2Sync(password, this.salt, 10000, 512, "sha512") - .toString("hex"); -}; - -UserSchema.methods.generateJWT = function() { - var today = new Date(); - var exp = new Date(today); - exp.setDate(today.getDate() + 60); - - return jwt.sign( - { - id: this._id, - username: this.username, - exp: parseInt(exp.getTime() / 1000) - }, - secret - ); -}; - -UserSchema.methods.toAuthJSON = function() { - return { - username: this.username, - email: this.email, - token: this.generateJWT(), - bio: this.bio, - image: this.image, - role: this.role - }; -}; - -UserSchema.methods.toProfileJSONFor = function(user) { - return { - username: this.username, - bio: this.bio, - image: - this.image || "https://static.productionready.io/images/smiley-cyrus.jpg", - following: user ? user.isFollowing(this._id) : false - }; -}; - -UserSchema.methods.favorite = function(id) { - if (this.favorites.indexOf(id) === -1) { - this.favorites = this.favorites.concat([id]); - } - - return this.save(); -}; - -UserSchema.methods.unfavorite = function(id) { - this.favorites.remove(id); - return this.save(); -}; - -UserSchema.methods.isFavorite = function(id) { - return this.favorites.some(function(favoriteId) { - return favoriteId.toString() === id.toString(); - }); -}; - -UserSchema.methods.follow = function(id) { - if (this.following.indexOf(id) === -1) { - this.following = this.following.concat([id]); - } - - return this.save(); -}; - -UserSchema.methods.unfollow = function(id) { - this.following.remove(id); - return this.save(); -}; - -UserSchema.methods.isFollowing = function(id) { - return this.following.some(function(followId) { - return followId.toString() === id.toString(); - }); -}; - -mongoose.model("User", UserSchema); diff --git a/.framework/node/backend/package.json b/.framework/node/backend/package.json deleted file mode 100644 index 4dcd6eb..0000000 --- a/.framework/node/backend/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "anythink-market-backend", - "version": "1.0.0", - "main": "app.js", - "engines": { - "node": "^16" - }, - "scripts": { - "start": "node ./app.js", - "dev": "nodemon ./app.js", - "seeds": "node ./scripts/seeds.js", - "test": "newman run ./tests/api-tests.postman.json -e ./tests/env-api-tests.postman.json", - "stop": "lsof -ti :3000 | xargs kill" - }, - "dependencies": { - "axios": "^0.25.0", - "body-parser": "1.15.0", - "cors": "2.7.1", - "dotenv": "^8.2.0", - "ejs": "2.4.1", - "errorhandler": "1.4.3", - "express": "4.13.4", - "express-async-handler": "^1.2.0", - "express-jwt": "3.3.0", - "express-session": "1.13.0", - "jsonwebtoken": "7.1.9", - "method-override": "2.3.5", - "methods": "1.1.2", - "mongoose": "5.12.5", - "mongoose-unique-validator": "^3.0.0", - "morgan": "1.7.0", - "passport": "0.3.2", - "passport-local": "1.0.0", - "request": "2.69.0", - "slug": "0.9.1", - "underscore": "1.8.3" - }, - "devDependencies": { - "newman": "^3.8.2", - "nodemon": "^1.11.0" - } -} diff --git a/.framework/node/backend/routes/api/index.js b/.framework/node/backend/routes/api/index.js deleted file mode 100644 index 380d027..0000000 --- a/.framework/node/backend/routes/api/index.js +++ /dev/null @@ -1,23 +0,0 @@ -var router = require('express').Router(); - -router.use('/', require('./users')); -router.use('/profiles', require('./profiles')); -router.use('/items', require('./items')); -router.use('/tags', require('./tags')); -router.use('/ping', require('./ping')); - -router.use(function(err, req, res, next){ - if(err.name === 'ValidationError'){ - return res.status(422).json({ - errors: Object.keys(err.errors).reduce(function(errors, key){ - errors[key] = err.errors[key].message; - - return errors; - }, {}) - }); - } - - return next(err); -}); - -module.exports = router; \ No newline at end of file diff --git a/.framework/node/backend/routes/api/items.js b/.framework/node/backend/routes/api/items.js deleted file mode 100644 index 84a8af9..0000000 --- a/.framework/node/backend/routes/api/items.js +++ /dev/null @@ -1,331 +0,0 @@ -var router = require("express").Router(); -var mongoose = require("mongoose"); -var Item = mongoose.model("Item"); -var Comment = mongoose.model("Comment"); -var User = mongoose.model("User"); -var auth = require("../auth"); -const { sendEvent } = require("../../lib/event"); - -// Preload item objects on routes with ':item' -router.param("item", function(req, res, next, slug) { - Item.findOne({ slug: slug }) - .populate("seller") - .then(function(item) { - if (!item) { - return res.sendStatus(404); - } - - req.item = item; - - return next(); - }) - .catch(next); -}); - -router.param("comment", function(req, res, next, id) { - Comment.findById(id) - .then(function(comment) { - if (!comment) { - return res.sendStatus(404); - } - - req.comment = comment; - - return next(); - }) - .catch(next); -}); - -router.get("/", auth.optional, function(req, res, next) { - var query = {}; - var limit = 100; - var offset = 0; - - if (typeof req.query.limit !== "undefined") { - limit = req.query.limit; - } - - if (typeof req.query.offset !== "undefined") { - offset = req.query.offset; - } - - if (typeof req.query.tag !== "undefined") { - query.tagList = { $in: [req.query.tag] }; - } - - Promise.all([ - req.query.seller ? User.findOne({ username: req.query.seller }) : null, - req.query.favorited ? User.findOne({ username: req.query.favorited }) : null - ]) - .then(function(results) { - var seller = results[0]; - var favoriter = results[1]; - - if (seller) { - query.seller = seller._id; - } - - if (favoriter) { - query._id = { $in: favoriter.favorites }; - } else if (req.query.favorited) { - query._id = { $in: [] }; - } - - return Promise.all([ - Item.find(query) - .limit(Number(limit)) - .skip(Number(offset)) - .sort({ createdAt: "desc" }) - .exec(), - Item.count(query).exec(), - req.payload ? User.findById(req.payload.id) : null - ]).then(async function(results) { - var items = results[0]; - var itemsCount = results[1]; - var user = results[2]; - return res.json({ - items: await Promise.all( - items.map(async function(item) { - item.seller = await User.findById(item.seller); - return item.toJSONFor(user); - }) - ), - itemsCount: itemsCount - }); - }); - }) - .catch(next); -}); - -router.get("/feed", auth.required, function(req, res, next) { - var limit = 20; - var offset = 0; - - if (typeof req.query.limit !== "undefined") { - limit = req.query.limit; - } - - if (typeof req.query.offset !== "undefined") { - offset = req.query.offset; - } - - User.findById(req.payload.id).then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - Promise.all([ - Item.find({ seller: { $in: user.following } }) - .limit(Number(limit)) - .skip(Number(offset)) - .populate("seller") - .exec(), - Item.count({ seller: { $in: user.following } }) - ]) - .then(function(results) { - var items = results[0]; - var itemsCount = results[1]; - - return res.json({ - items: items.map(function(item) { - return item.toJSONFor(user); - }), - itemsCount: itemsCount - }); - }) - .catch(next); - }); -}); - -router.post("/", auth.required, function(req, res, next) { - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - var item = new Item(req.body.item); - - item.seller = user; - - return item.save().then(function() { - sendEvent('item_created', { item: req.body.item }) - return res.json({ item: item.toJSONFor(user) }); - }); - }) - .catch(next); -}); - -// return a item -router.get("/:item", auth.optional, function(req, res, next) { - Promise.all([ - req.payload ? User.findById(req.payload.id) : null, - req.item.populate("seller").execPopulate() - ]) - .then(function(results) { - var user = results[0]; - - return res.json({ item: req.item.toJSONFor(user) }); - }) - .catch(next); -}); - -// update item -router.put("/:item", auth.required, function(req, res, next) { - User.findById(req.payload.id).then(function(user) { - if (req.item.seller._id.toString() === req.payload.id.toString()) { - if (typeof req.body.item.title !== "undefined") { - req.item.title = req.body.item.title; - } - - if (typeof req.body.item.description !== "undefined") { - req.item.description = req.body.item.description; - } - - if (typeof req.body.item.image !== "undefined") { - req.item.image = req.body.item.image; - } - - if (typeof req.body.item.tagList !== "undefined") { - req.item.tagList = req.body.item.tagList; - } - - req.item - .save() - .then(function(item) { - return res.json({ item: item.toJSONFor(user) }); - }) - .catch(next); - } else { - return res.sendStatus(403); - } - }); -}); - -// delete item -router.delete("/:item", auth.required, function(req, res, next) { - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - if (req.item.seller._id.toString() === req.payload.id.toString()) { - return req.item.remove().then(function() { - return res.sendStatus(204); - }); - } else { - return res.sendStatus(403); - } - }) - .catch(next); -}); - -// Favorite an item -router.post("/:item/favorite", auth.required, function(req, res, next) { - var itemId = req.item._id; - - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - return user.favorite(itemId).then(function() { - return req.item.updateFavoriteCount().then(function(item) { - return res.json({ item: item.toJSONFor(user) }); - }); - }); - }) - .catch(next); -}); - -// Unfavorite an item -router.delete("/:item/favorite", auth.required, function(req, res, next) { - var itemId = req.item._id; - - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - return user.unfavorite(itemId).then(function() { - return req.item.updateFavoriteCount().then(function(item) { - return res.json({ item: item.toJSONFor(user) }); - }); - }); - }) - .catch(next); -}); - -// return an item's comments -router.get("/:item/comments", auth.optional, function(req, res, next) { - Promise.resolve(req.payload ? User.findById(req.payload.id) : null) - .then(function(user) { - return req.item - .populate({ - path: "comments", - populate: { - path: "seller" - }, - options: { - sort: { - createdAt: "desc" - } - } - }) - .execPopulate() - .then(function(item) { - return res.json({ - comments: req.item.comments.map(function(comment) { - return comment.toJSONFor(user); - }) - }); - }); - }) - .catch(next); -}); - -// create a new comment -router.post("/:item/comments", auth.required, function(req, res, next) { - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - var comment = new Comment(req.body.comment); - comment.item = req.item; - comment.seller = user; - - return comment.save().then(function() { - req.item.comments = req.item.comments.concat([comment]); - - return req.item.save().then(function(item) { - res.json({ comment: comment.toJSONFor(user) }); - }); - }); - }) - .catch(next); -}); - -router.delete("/:item/comments/:comment", auth.required, function( - req, - res, - next -) { - req.item.comments.remove(req.comment._id); - req.item - .save() - .then( - Comment.find({ _id: req.comment._id }) - .remove() - .exec() - ) - .then(function() { - res.sendStatus(204); - }); -}); - -module.exports = router; diff --git a/.framework/node/backend/routes/api/ping.js b/.framework/node/backend/routes/api/ping.js deleted file mode 100644 index a327948..0000000 --- a/.framework/node/backend/routes/api/ping.js +++ /dev/null @@ -1,19 +0,0 @@ -const router = require("express").Router(); -const asyncHandler = require("express-async-handler"); -const auth = require("../auth"); -const { sendEvent } = require("../../lib/event"); - -router.get("/", - auth.optional, - asyncHandler(async (req, res) => { - - try { - const result = await sendEvent('ping') - return res.json(result); - } catch (e) { - console.error(e) - return res.sendStatus(500); - } - })); - -module.exports = router; diff --git a/.framework/node/backend/routes/api/profiles.js b/.framework/node/backend/routes/api/profiles.js deleted file mode 100644 index ffcd833..0000000 --- a/.framework/node/backend/routes/api/profiles.js +++ /dev/null @@ -1,53 +0,0 @@ -var router = require('express').Router(); -var mongoose = require('mongoose'); -var User = mongoose.model('User'); -var auth = require('../auth'); - -// Preload user profile on routes with ':username' -router.param('username', function(req, res, next, username){ - User.findOne({username: username}).then(function(user){ - if (!user) { return res.sendStatus(404); } - - req.profile = user; - - return next(); - }).catch(next); -}); - -router.get('/:username', auth.optional, function(req, res, next){ - if(req.payload){ - User.findById(req.payload.id).then(function(user){ - if(!user){ return res.json({profile: req.profile.toProfileJSONFor(false)}); } - - return res.json({profile: req.profile.toProfileJSONFor(user)}); - }); - } else { - return res.json({profile: req.profile.toProfileJSONFor(false)}); - } -}); - -router.post('/:username/follow', auth.required, function(req, res, next){ - var profileId = req.profile._id; - - User.findById(req.payload.id).then(function(user){ - if (!user) { return res.sendStatus(401); } - - return user.follow(profileId).then(function(){ - return res.json({profile: req.profile.toProfileJSONFor(user)}); - }); - }).catch(next); -}); - -router.delete('/:username/follow', auth.required, function(req, res, next){ - var profileId = req.profile._id; - - User.findById(req.payload.id).then(function(user){ - if (!user) { return res.sendStatus(401); } - - return user.unfollow(profileId).then(function(){ - return res.json({profile: req.profile.toProfileJSONFor(user)}); - }); - }).catch(next); -}); - -module.exports = router; diff --git a/.framework/node/backend/routes/api/tags.js b/.framework/node/backend/routes/api/tags.js deleted file mode 100644 index 2090495..0000000 --- a/.framework/node/backend/routes/api/tags.js +++ /dev/null @@ -1,12 +0,0 @@ -var router = require('express').Router(); -var mongoose = require('mongoose'); -var Item = mongoose.model('Item'); - -// return a list of tags -router.get('/', function(req, res, next) { - Item.find().distinct('tagList').then(function(tags){ - return res.json({tags: tags}); - }).catch(next); -}); - -module.exports = router; diff --git a/.framework/node/backend/routes/api/users.js b/.framework/node/backend/routes/api/users.js deleted file mode 100644 index aeae77f..0000000 --- a/.framework/node/backend/routes/api/users.js +++ /dev/null @@ -1,90 +0,0 @@ -var mongoose = require("mongoose"); -var router = require("express").Router(); -var passport = require("passport"); -var User = mongoose.model("User"); -var auth = require("../auth"); -const { sendEvent } = require("../../lib/event"); - -router.get("/user", auth.required, function(req, res, next) { - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - return res.json({ user: user.toAuthJSON() }); - }) - .catch(next); -}); - -router.put("/user", auth.required, function(req, res, next) { - User.findById(req.payload.id) - .then(function(user) { - if (!user) { - return res.sendStatus(401); - } - - // only update fields that were actually passed... - if (typeof req.body.user.username !== "undefined") { - user.username = req.body.user.username; - } - if (typeof req.body.user.email !== "undefined") { - user.email = req.body.user.email; - } - if (typeof req.body.user.bio !== "undefined") { - user.bio = req.body.user.bio; - } - if (typeof req.body.user.image !== "undefined") { - user.image = req.body.user.image; - } - if (typeof req.body.user.password !== "undefined") { - user.setPassword(req.body.user.password); - } - - return user.save().then(function() { - return res.json({ user: user.toAuthJSON() }); - }); - }) - .catch(next); -}); - -router.post("/users/login", function(req, res, next) { - if (!req.body.user.email) { - return res.status(422).json({ errors: { email: "can't be blank" } }); - } - - if (!req.body.user.password) { - return res.status(422).json({ errors: { password: "can't be blank" } }); - } - - passport.authenticate("local", { session: false }, function(err, user, info) { - if (err) { - return next(err); - } - - if (user) { - user.token = user.generateJWT(); - return res.json({ user: user.toAuthJSON() }); - } else { - return res.status(422).json(info); - } - })(req, res, next); -}); - -router.post("/users", function(req, res, next) { - var user = new User(); - - user.username = req.body.user.username; - user.email = req.body.user.email; - user.setPassword(req.body.user.password); - - user - .save() - .then(function() { - sendEvent('user_created', { username: req.body.user.username }) - return res.json({ user: user.toAuthJSON() }); - }) - .catch(next); -}); - -module.exports = router; diff --git a/.framework/node/backend/routes/auth.js b/.framework/node/backend/routes/auth.js deleted file mode 100644 index e44a215..0000000 --- a/.framework/node/backend/routes/auth.js +++ /dev/null @@ -1,27 +0,0 @@ -var jwt = require('express-jwt'); -var secret = require('../config').secret; - -function getTokenFromHeader(req){ - if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Token' || - req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') { - return req.headers.authorization.split(' ')[1]; - } - - return null; -} - -var auth = { - required: jwt({ - secret: secret, - userProperty: 'payload', - getToken: getTokenFromHeader - }), - optional: jwt({ - secret: secret, - userProperty: 'payload', - credentialsRequired: false, - getToken: getTokenFromHeader - }) -}; - -module.exports = auth; diff --git a/.framework/node/backend/routes/index.js b/.framework/node/backend/routes/index.js deleted file mode 100644 index 81d38f9..0000000 --- a/.framework/node/backend/routes/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var router = require('express').Router(); - -router.get('/', (req, res, next) => { - res.send("Anythink backend is up."); -}); - -router.get('/health', (req, res, next) => { - res.sendStatus("200"); -}) - -router.use('/api', require('./api')); - -module.exports = router; diff --git a/.framework/node/backend/scripts/seeds.js b/.framework/node/backend/scripts/seeds.js deleted file mode 100644 index 4989da1..0000000 --- a/.framework/node/backend/scripts/seeds.js +++ /dev/null @@ -1 +0,0 @@ -//TODO: seeds script should come here, so we'll be able to put some data in our local env diff --git a/.framework/node/backend/seeds.sh b/.framework/node/backend/seeds.sh deleted file mode 100755 index 855f73d..0000000 --- a/.framework/node/backend/seeds.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -yarn seeds diff --git a/.framework/node/backend/tests/api-tests.postman.json b/.framework/node/backend/tests/api-tests.postman.json deleted file mode 100644 index fcfaf1a..0000000 --- a/.framework/node/backend/tests/api-tests.postman.json +++ /dev/null @@ -1,1900 +0,0 @@ -{ - "variables": [], - "info": { - "name": "Anythink-Market API Tests", - "_postman_id": "dda3e595-02d7-bf12-2a43-3daea0970192", - "description": "Collection for testing the Anythink-Market API\n\nhttps://github.com/gothinkster/realworld", - "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" - }, - "item": [{ - "name": "Auth", - "description": "", - "item": [{ - "name": "Register", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "if (!(environment.isIntegrationTest)) {", - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"user\" property'] = responseJSON.hasOwnProperty('user');", - "", - "var user = responseJSON.user || {};", - "", - "tests['User has \"email\" property'] = user.hasOwnProperty('email');", - "tests['User has \"username\" property'] = user.hasOwnProperty('username');", - "tests['User has \"token\" property'] = user.hasOwnProperty('token');", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/users", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"user\":{\"email\":\"john@jacob.com\", \"password\":\"johnnyjacob\", \"username\":\"johnjacob\"}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Login", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"user\" property'] = responseJSON.hasOwnProperty('user');", - "", - "var user = responseJSON.user || {};", - "", - "tests['User has \"email\" property'] = user.hasOwnProperty('email');", - "tests['User has \"username\" property'] = user.hasOwnProperty('username');", - "tests['User has \"token\" property'] = user.hasOwnProperty('token');", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/users/login", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"user\":{\"email\":\"john@jacob.com\", \"password\":\"johnnyjacob\"}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Login and Remember Token", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"user\" property'] = responseJSON.hasOwnProperty('user');", - "", - "var user = responseJSON.user || {};", - "", - "tests['User has \"email\" property'] = user.hasOwnProperty('email');", - "tests['User has \"username\" property'] = user.hasOwnProperty('username');", - "tests['User has \"token\" property'] = user.hasOwnProperty('token');", - "", - "if(tests['User has \"token\" property']){", - " postman.setEnvironmentVariable('token', user.token);", - "}", - "", - "tests['Environment variable \"token\" has been set'] = environment.token === user.token;", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/users/login", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"user\":{\"email\":\"john@jacob.com\", \"password\":\"johnnyjacob\"}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Current User", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"user\" property'] = responseJSON.hasOwnProperty('user');", - "", - "var user = responseJSON.user || {};", - "", - "tests['User has \"email\" property'] = user.hasOwnProperty('email');", - "tests['User has \"username\" property'] = user.hasOwnProperty('username');", - "tests['User has \"token\" property'] = user.hasOwnProperty('token');", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/user", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - }, - { - "name": "Update User", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"user\" property'] = responseJSON.hasOwnProperty('user');", - "", - "var user = responseJSON.user || {};", - "", - "tests['User has \"email\" property'] = user.hasOwnProperty('email');", - "tests['User has \"username\" property'] = user.hasOwnProperty('username');", - "tests['User has \"token\" property'] = user.hasOwnProperty('token');", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/user", - "method": "PUT", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"user\":{\"email\":\"john@jacob.com\"}}" - }, - "description": "" - }, - "response": [] - } - ] - }, - { - "name": "Items with authentication", - "description": "", - "item": [{ - "name": "Feed", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/feed", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "All Items", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "All Items with auth", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items by Author", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?seller=johnjacob", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "seller", - "value": "johnjacob" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items by Author with auth", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?seller=johnjacob", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "seller", - "value": "johnjacob", - "equals": true, - "description": "" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - }, - { - "name": "Items Favorited by Username", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - " ", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?favorited=jane", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "favorited", - "value": "jane" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items Favorited by Username with auth", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - " ", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?favorited=jane", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "favorited", - "value": "jane" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items by Tag", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?tag=dragons", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "tag", - "value": "dragons" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Create Item", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"item\" property'] = responseJSON.hasOwnProperty('item');", - "", - "var item = responseJSON.item || {};", - "", - "tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - "tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - "if(tests['Item has \"slug\" property']){", - " postman.setEnvironmentVariable('slug', item.slug);", - "}", - "tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - "tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - "tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - "tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - "tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - "tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - "tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - "tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - "tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - "tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - "tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - "tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"item\":{\"title\":\"How to train your dragon\", \"description\":\"Ever wonder how?\", \"body\":\"Very carefully.\", \"tagList\":[\"dragons\",\"training\"]}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Single Item by slug", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"item\" property'] = responseJSON.hasOwnProperty('item');", - "", - "var item = responseJSON.item || {};", - "", - "tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - "tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - "tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - "tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - "tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - "tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - "tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - "tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - "tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - "tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - "tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - "tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - "tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - "tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - }, - { - "name": "Update Item", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "if (!(environment.isIntegrationTest)) {", - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"item\" property'] = responseJSON.hasOwnProperty('item');", - "", - "var item = responseJSON.item || {};", - "", - "tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - "tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - "tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - "tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - "tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - "tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - "tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - "tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - "tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - "tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - "tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - "tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - "tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - "tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}", - "method": "PUT", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"item\":{\"body\":\"With two hands\"}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Favorite Item", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"item\" property'] = responseJSON.hasOwnProperty('item');", - "", - "var item = responseJSON.item || {};", - "", - "tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - "tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - "tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - "tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - "tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - "tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - "tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - "tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - "tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - "tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - "tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - "tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - "tests[\"Item's 'favorited' property is true\"] = item.favorited === true;", - "tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - "tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - "tests[\"Item's 'favoritesCount' property is greater than 0\"] = item.favoritesCount > 0;", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}/favorite", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Unfavorite Item", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"item\" property'] = responseJSON.hasOwnProperty('item');", - "", - "var item = responseJSON.item || {};", - "", - "tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - "tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - "tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - "tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - "tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - "tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - "tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - "tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - "tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - "tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - "tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - "tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - "tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - "tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - "tests[\"Item's \\\"favorited\\\" property is true\"] = item.favorited === false;", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}/favorite", - "method": "DELETE", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - } - ] - }, - { - "name": "Items", - "description": "", - "item": [{ - "name": "All Items", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items by Author", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?seller=johnjacob", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "seller", - "value": "johnjacob" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items Favorited by Username", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - " ", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?favorited=jane", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "favorited", - "value": "jane" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Items by Tag", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"items\" property'] = responseJSON.hasOwnProperty('items');", - " tests['Response contains \"itemsCount\" property'] = responseJSON.hasOwnProperty('itemsCount');", - " tests['itemsCount is an integer'] = Number.isInteger(responseJSON.itemsCount);", - "", - " if(responseJSON.items.length){", - " var item = responseJSON.items[0];", - "", - " tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - " tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - " tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - " tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - " tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - " tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - " tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - " tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - " tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - " tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - " tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - " tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - " tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - " tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - " } else {", - " tests['itemsCount is 0 when feed is empty'] = responseJSON.itemsCount === 0;", - " }", - "}", - "" - ] - } - }], - "request": { - "url": { - "raw": "{{apiUrl}}/items?tag=dragons", - "host": [ - "{{apiUrl}}" - ], - "path": [ - "items" - ], - "query": [{ - "key": "tag", - "value": "dragons" - }], - "variable": [] - }, - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Single Item by slug", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"item\" property'] = responseJSON.hasOwnProperty('item');", - "", - "var item = responseJSON.item || {};", - "", - "tests['Item has \"title\" property'] = item.hasOwnProperty('title');", - "tests['Item has \"slug\" property'] = item.hasOwnProperty('slug');", - "tests['Item has \"body\" property'] = item.hasOwnProperty('body');", - "tests['Item has \"createdAt\" property'] = item.hasOwnProperty('createdAt');", - "tests['Item\\'s \"createdAt\" property is an ISO 8601 timestamp'] = new Date(item.createdAt).toISOString() === item.createdAt;", - "tests['Item has \"updatedAt\" property'] = item.hasOwnProperty('updatedAt');", - "tests['Item\\'s \"updatedAt\" property is an ISO 8601 timestamp'] = new Date(item.updatedAt).toISOString() === item.updatedAt;", - "tests['Item has \"description\" property'] = item.hasOwnProperty('description');", - "tests['Item has \"tagList\" property'] = item.hasOwnProperty('tagList');", - "tests['Item\\'s \"tagList\" property is an Array'] = Array.isArray(item.tagList);", - "tests['Item has \"seller\" property'] = item.hasOwnProperty('seller');", - "tests['Item has \"favorited\" property'] = item.hasOwnProperty('favorited');", - "tests['Item has \"favoritesCount\" property'] = item.hasOwnProperty('favoritesCount');", - "tests['favoritesCount is an integer'] = Number.isInteger(item.favoritesCount);", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - } - ] - }, - { - "name": "Comments", - "description": "", - "item": [{ - "name": "All Comments for Item", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"comments\" property'] = responseJSON.hasOwnProperty('comments');", - "", - " if(responseJSON.comments.length){", - " var comment = responseJSON.comments[0];", - "", - " tests['Comment has \"id\" property'] = comment.hasOwnProperty('id');", - " tests['Comment has \"body\" property'] = comment.hasOwnProperty('body');", - " tests['Comment has \"createdAt\" property'] = comment.hasOwnProperty('createdAt');", - " tests['\"createdAt\" property is an ISO 8601 timestamp'] = new Date(comment.createdAt).toISOString() === comment.createdAt;", - " tests['Comment has \"updatedAt\" property'] = comment.hasOwnProperty('updatedAt');", - " tests['\"updatedAt\" property is an ISO 8601 timestamp'] = new Date(comment.updatedAt).toISOString() === comment.updatedAt;", - " tests['Comment has \"seller\" property'] = comment.hasOwnProperty('seller');", - " }", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}/comments", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - }, - { - "name": "Create Comment for Item", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var responseJSON = JSON.parse(responseBody);", - "", - "tests['Response contains \"comment\" property'] = responseJSON.hasOwnProperty('comment');", - "", - "var comment = responseJSON.comment || {};", - "", - "tests['Comment has \"id\" property'] = comment.hasOwnProperty('id');", - "tests['Comment has \"body\" property'] = comment.hasOwnProperty('body');", - "tests['Comment has \"createdAt\" property'] = comment.hasOwnProperty('createdAt');", - "tests['\"createdAt\" property is an ISO 8601 timestamp'] = new Date(comment.createdAt).toISOString() === comment.createdAt;", - "tests['Comment has \"seller\" property'] = comment.hasOwnProperty('seller');", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/items/{{slug}}/comments", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"comment\":{\"body\":\"Thank you so much!\"}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Delete Comment for Item", - "request": { - "url": "{{apiUrl}}/items/{{slug}}/comments/1", - "method": "DELETE", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - } - ] - }, - { - "name": "Profiles", - "description": "", - "item": [{ - "name": "Profile", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "if (!(environment.isIntegrationTest)) {", - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"profile\" property'] = responseJSON.hasOwnProperty('profile');", - " ", - " var profile = responseJSON.profile || {};", - " ", - " tests['Profile has \"username\" property'] = profile.hasOwnProperty('username');", - " tests['Profile has \"image\" property'] = profile.hasOwnProperty('image');", - " tests['Profile has \"following\" property'] = profile.hasOwnProperty('following');", - "}", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/profiles/johnjacob", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - }, - { - "name": "Follow Profile", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "if (!(environment.isIntegrationTest)) {", - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"profile\" property'] = responseJSON.hasOwnProperty('profile');", - " ", - " var profile = responseJSON.profile || {};", - " ", - " tests['Profile has \"username\" property'] = profile.hasOwnProperty('username');", - " tests['Profile has \"image\" property'] = profile.hasOwnProperty('image');", - " tests['Profile has \"following\" property'] = profile.hasOwnProperty('following');", - " tests['Profile\\'s \"following\" property is true'] = profile.following === true;", - "}", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/profiles/johnjacob/follow", - "method": "POST", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "{\"user\":{\"email\":\"john@jacob.com\"}}" - }, - "description": "" - }, - "response": [] - }, - { - "name": "Unfollow Profile", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "if (!(environment.isIntegrationTest)) {", - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - "", - " tests['Response contains \"profile\" property'] = responseJSON.hasOwnProperty('profile');", - " ", - " var profile = responseJSON.profile || {};", - " ", - " tests['Profile has \"username\" property'] = profile.hasOwnProperty('username');", - " tests['Profile has \"image\" property'] = profile.hasOwnProperty('image');", - " tests['Profile has \"following\" property'] = profile.hasOwnProperty('following');", - " tests['Profile\\'s \"following\" property is false'] = profile.following === false;", - "}", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/profiles/johnjacob/follow", - "method": "DELETE", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": {}, - "description": "" - }, - "response": [] - } - ] - }, - { - "name": "Tags", - "description": "", - "item": [{ - "name": "All Tags", - "event": [{ - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "var is200Response = responseCode.code === 200;", - "", - "tests['Response code is 200 OK'] = is200Response;", - "", - "if(is200Response){", - " var responseJSON = JSON.parse(responseBody);", - " ", - " tests['Response contains \"tags\" property'] = responseJSON.hasOwnProperty('tags');", - " tests['\"tags\" property returned as array'] = Array.isArray(responseJSON.tags);", - "}", - "" - ] - } - }], - "request": { - "url": "{{apiUrl}}/tags", - "method": "GET", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }] - }, - { - "name": "Cleanup", - "description": "", - "item": [{ - "name": "Delete Item", - "request": { - "url": "{{apiUrl}}/items/{{slug}}", - "method": "DELETE", - "header": [{ - "key": "Content-Type", - "value": "application/json", - "description": "" - }, - { - "key": "X-Requested-With", - "value": "XMLHttpRequest", - "description": "" - }, - { - "key": "Authorization", - "value": "Token {{token}}", - "description": "" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "description": "" - }, - "response": [] - }] - } - ] -} diff --git a/.framework/node/backend/tests/env-api-tests.postman.json b/.framework/node/backend/tests/env-api-tests.postman.json deleted file mode 100644 index 3ba2ebf..0000000 --- a/.framework/node/backend/tests/env-api-tests.postman.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "4aa60b52-97fc-456d-4d4f-14a350e95dff", - "name": "Anythink-Market API Tests - Environment", - "values": [{ - "enabled": true, - "key": "apiUrl", - "value": "http://localhost:3000/api", - "type": "text" - }], - "timestamp": 1505871382668, - "_postman_variable_scope": "environment", - "_postman_exported_at": "2017-09-20T01:36:34.835Z", - "_postman_exported_using": "Postman/5.2.0" -} diff --git a/.framework/node/backend/yarn.lock b/.framework/node/backend/yarn.lock deleted file mode 100644 index d00f449..0000000 --- a/.framework/node/backend/yarn.lock +++ /dev/null @@ -1,3648 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@types/bson@*": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/bson/-/bson-4.2.0.tgz#a2f71e933ff54b2c3bf267b67fa221e295a33337" - integrity sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg== - dependencies: - bson "*" - -"@types/mongodb@^3.5.27": - version "3.6.20" - resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.6.20.tgz#b7c5c580644f6364002b649af1c06c3c0454e1d2" - integrity sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ== - dependencies: - "@types/bson" "*" - "@types/node" "*" - -"@types/node@*": - version "17.0.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.0.tgz#62797cee3b8b497f6547503b2312254d4fe3c2bb" - integrity sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -accepts@~1.2.12: - version "1.2.13" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" - integrity sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo= - dependencies: - mime-types "~2.1.6" - negotiator "0.5.3" - -accepts@~1.3.0: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= - dependencies: - string-width "^2.0.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== - dependencies: - lodash "^4.17.10" - -async@^0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= - -async@^1.4.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -async@^2.0.1: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" - integrity sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w== - -aws4@^1.2.1, aws4@^1.6.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - -axios@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== - dependencies: - follow-redirects "^1.14.7" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -base64-url@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-1.2.1.tgz#199fd661702a0e7b7dcae6e0698bb089c52f6d78" - integrity sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg= - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -basic-auth@~1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" - integrity sha1-Awk1sB3nyblKgksp8/zLdQ06UpA= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bl@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" - integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -bl@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.0.3.tgz#fc5421a28fd4226036c3b3891a66a25bc64d226e" - integrity sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4= - dependencies: - readable-stream "~2.0.5" - -bluebird@3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== - -bluebird@^2.6.2: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= - -body-parser@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.15.0.tgz#8168abaeaf9e77e300f7b3aef4df4b46e9b21b35" - integrity sha1-gWirrq+ed+MA97Ou9N9LRumyGzU= - dependencies: - bytes "2.2.0" - content-type "~1.0.1" - debug "~2.2.0" - depd "~1.1.0" - http-errors "~1.4.0" - iconv-lite "0.4.13" - on-finished "~2.3.0" - qs "6.1.0" - raw-body "~2.1.5" - type-is "~1.6.11" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE= - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== - dependencies: - hoek "4.x.x" - -boxen@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -bson@*: - version "4.6.0" - resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.0.tgz#15c3b39ba3940c3d915a0c44d51459f4b4fbf1b2" - integrity sha512-8jw1NU1hglS+Da1jDOUYuNcBJ4cNHCFIqzlwoFNnsTOg2R/ox0aTYcTiBN4dzRa9q7Cvy6XErh3L8ReTEb9AQQ== - dependencies: - buffer "^5.6.0" - -bson@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.6.tgz#fb819be9a60cd677e0853aee4ca712a785d6618a" - integrity sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg== - -btoa@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" - integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== - -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= - -buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bytes@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.2.0.tgz#fd35464a403f6f9117c2de3609ecff9cae000588" - integrity sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg= - -bytes@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" - integrity sha1-fZcZb51br39pNeJZhVSe3SpsIzk= - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= - -camelcase@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - -capture-stack-trace@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" - integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - integrity sha1-cVuW6phBWTzDMGeSP17GDr2k99c= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chalk@^1.1.0, chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -charset@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/charset/-/charset-1.0.1.tgz#8d59546c355be61049a8fa9164747793319852bd" - integrity sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg== - -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -ci-info@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== - -circular-json@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" - integrity sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0= - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= - -cli-progress@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-1.8.0.tgz#5e8afc310f2058fbe33e9006e31c71c1c3b5da7f" - integrity sha1-Xor8MQ8gWPvjPpAG4xxxwcO12n8= - dependencies: - colors "^1.1.2" - -cli-table3@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.4.0.tgz#a7fd50f011d734e3f16403cfcbedbea97659e417" - integrity sha512-o0slI6EFJNI2aKE9jG1bVN6jXJG2vjzYsGhyd9RqRV/YiiEmzSwNNXb5qJmfLDSOdvfA6sUvdKVvi3p3Y1apxA== - dependencies: - kind-of "^3.0.4" - object-assign "^4.1.0" - string-width "^1.0.1" - optionalDependencies: - colors "^1.1.2" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -colors@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e" - integrity sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw== - -colors@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - -combined-stream@^1.0.5, combined-stream@^1.0.6, combined-stream@~1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@2.16.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" - integrity sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew== - -commander@^2.9.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -configstore@^3.0.0: - version "3.1.5" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.5.tgz#e9af331fadc14dabd544d3e7e76dc446a09a530f" - integrity sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA== - dependencies: - dot-prop "^4.2.1" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - -content-disposition@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" - integrity sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs= - -content-type@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.5.tgz#6ab9948a4b1ae21952cd2588530a4722d4044d7c" - integrity sha1-armUiksa4hlSzSWIUwpHItQETXw= - -cookie@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.2.3.tgz#1a59536af68537a21178a01346f87cb059d2ae5c" - integrity sha1-GllTavaFN6IReKATRvh8sFnSrlw= - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cors@2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.7.1.tgz#3c2e50a58af9ef8c89bee21226b099be1f02739b" - integrity sha1-PC5QpYr574yJvuISJrCZvh8Cc5s= - dependencies: - vary "^1" - -crc@3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.0.tgz#4258e351613a74ef1153dfcb05e820c3e9715d7f" - integrity sha1-QljjUWE6dO8RU9/LBeggw+lxXX8= - -create-error-class@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= - dependencies: - capture-stack-trace "^1.0.0" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.4" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.4.tgz#769a68c95612b56faadfcebf57ac86479cbe8322" - integrity sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw== - dependencies: - boom "5.x.x" - -crypto-js@3.1.9-1: - version "3.1.9-1" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8" - integrity sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg= - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= - -csv-parse@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-1.3.3.tgz#d1cfd8743c2f849a0abb2fd544db56695d19a490" - integrity sha1-0c/YdDwvhJoKuy/VRNtWaV0ZpJA= - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -dbug@~0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/dbug/-/dbug-0.4.2.tgz#32b4b3105e8861043a6f9ac755d80e542d365b31" - integrity sha1-MrSzEF6IYQQ6b5rHVdgOVC02WzE= - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.6: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= - dependencies: - ms "0.7.1" - -decamelize@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -denque@^1.4.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" - integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== - -depd@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -domelementtype@1, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" - integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== - dependencies: - is-obj "^1.0.0" - -dotenv@^8.2.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" - integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -ejs@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.4.1.tgz#82e15b1b2a1f948b18097476ba2bd7c66f4d1566" - integrity sha1-guFbGyoflIsYCXR2uivXxm9NFWY= - -entities@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -errorhandler@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.4.3.tgz#b7b70ed8f359e9db88092f2d20c0f831420ad83f" - integrity sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8= - dependencies: - accepts "~1.3.0" - escape-html "~1.0.3" - -escape-html@1.0.3, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -etag@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" - integrity sha1-A9MLX2fdbmMtKUXTDWZScxo01dg= - -eventemitter3@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" - integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -express-async-handler@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/express-async-handler/-/express-async-handler-1.2.0.tgz#ffc9896061d90f8d2e71a2d2b8668db5b0934391" - integrity sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w== - -express-jwt@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/express-jwt/-/express-jwt-3.3.0.tgz#d10e17244225b1968d20137ff77fc7488c88f494" - integrity sha1-0Q4XJEIlsZaNIBN/93/HSIyI9JQ= - dependencies: - async "^0.9.0" - express-unless "^0.3.0" - jsonwebtoken "^5.0.0" - lodash "~3.10.1" - -express-session@1.13.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.13.0.tgz#8ac3b5c0188b48382851d88207b8e7746efb4011" - integrity sha1-isO1wBiLSDgoUdiCB7jndG77QBE= - dependencies: - cookie "0.2.3" - cookie-signature "1.0.6" - crc "3.4.0" - debug "~2.2.0" - depd "~1.1.0" - on-headers "~1.0.1" - parseurl "~1.3.0" - uid-safe "~2.0.0" - utils-merge "1.0.0" - -express-unless@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/express-unless/-/express-unless-0.3.1.tgz#2557c146e75beb903e2d247f9b5ba01452696e20" - integrity sha1-JVfBRudb65A+LSR/m1ugFFJpbiA= - -express@4.13.4: - version "4.13.4" - resolved "https://registry.yarnpkg.com/express/-/express-4.13.4.tgz#3c0b76f3c77590c8345739061ec0bd3ba067ec24" - integrity sha1-PAt288d1kMg0VzkGHsC9O6Bn7CQ= - dependencies: - accepts "~1.2.12" - array-flatten "1.1.1" - content-disposition "0.5.1" - content-type "~1.0.1" - cookie "0.1.5" - cookie-signature "1.0.6" - debug "~2.2.0" - depd "~1.1.0" - escape-html "~1.0.3" - etag "~1.7.0" - finalhandler "0.4.1" - fresh "0.3.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.1" - path-to-regexp "0.1.7" - proxy-addr "~1.0.10" - qs "4.0.0" - range-parser "~1.0.3" - send "0.13.1" - serve-static "~1.10.2" - type-is "~1.6.6" - utils-merge "1.0.0" - vary "~1.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@~3.0.0, extend@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -file-type@3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -filesize@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.1.tgz#85a17c6c59a94717d262d61230d4b0ebe3d4a14d" - integrity sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0= - dependencies: - debug "~2.2.0" - escape-html "~1.0.3" - on-finished "~2.3.0" - unpipe "~1.0.0" - -follow-redirects@^1.14.7: - version "1.14.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" - integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~1.0.0-rc3: - version "1.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" - integrity sha1-rjFduaSQf6BlUCMEpm13M0de43w= - dependencies: - async "^2.0.1" - combined-stream "^1.0.5" - mime-types "^2.1.11" - -form-data@~2.3.1: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" - integrity sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -generate-function@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= - dependencies: - ini "^1.3.4" - -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= - dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - -handlebars@4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" - integrity sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw= - dependencies: - async "^1.4.0" - optimist "^0.6.1" - source-map "^0.4.4" - optionalDependencies: - uglify-js "^2.6" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - integrity sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0= - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hawk@6.0.2, hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ== - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -hawk@~3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - -hoek@4.x.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" - integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== - -htmlparser2@^3.9.0: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-errors@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" - integrity sha1-GX4izevUGYWF6GlO9nhhl7ke2UI= - dependencies: - inherits "~2.0.1" - statuses "1" - -http-errors@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.4.0.tgz#6c0242dea6b3df7afda153c71089b31c6e82aabf" - integrity sha1-bAJC3qaz33r9oVPHEImzHG6Cqr8= - dependencies: - inherits "2.0.1" - statuses ">= 1.2.1 < 2" - -http-reasons@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/http-reasons/-/http-reasons-0.1.0.tgz#a953ca670078669dde142ce899401b9d6e85d3b4" - integrity sha1-qVPKZwB4Zp3eFCzomUAbnW6F07Q= - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -httpntlm@1.7.6: - version "1.7.6" - resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.7.6.tgz#6991e8352836007d67101b83db8ed0f915f906d0" - integrity sha1-aZHoNSg2AH1nEBuD247Q+RX5BtA= - dependencies: - httpreq ">=0.4.22" - underscore "~1.7.0" - -httpreq@>=0.4.22: - version "0.5.2" - resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.5.2.tgz#be6777292fa1038d7771d7c01d9a5e1219de951c" - integrity sha512-2Jm+x9WkExDOeFRrdBCBSpLPT5SokTcRHkunV3pjKmX/cx6av8zQ0WtHUMDrYb6O4hBFzNU6sxJEypvRUVYKnw== - -iconv-lite@0.4.13: - version "0.4.13" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" - integrity sha1-H4irpKsLFQjoMSrMOTRfNumS4vI= - -iconv-lite@0.4.22: - version "0.4.22" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.22.tgz#c6b16b9d05bc6c307dc9303a820412995d2eea95" - integrity sha512-1AinFBeDTnsvVEP+V1QBlHpM1UZZl7gWB6fcz7B1Ho+LI1dUh2sSrxoCfVt2PinRHzXAziSniEV3P7JbTDHcXA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -intel@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/intel/-/intel-1.2.0.tgz#11d1147eb6b3f4582bdf5337b37d541584e9e41e" - integrity sha1-EdEUfraz9Fgr31M3s31UFYTp5B4= - dependencies: - chalk "^1.1.0" - dbug "~0.4.2" - stack-trace "~0.0.9" - strftime "~0.10.0" - symbol "~0.3.1" - utcstring "~0.1.0" - -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -ipaddr.js@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.0.5.tgz#5fa78cf301b825c78abc3042d812723049ea23c7" - integrity sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c= - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-ci@^1.0.10: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== - dependencies: - ci-info "^1.5.0" - -is-core-module@^2.2.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== - dependencies: - has "^1.0.3" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-installed-globally@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= - dependencies: - global-dirs "^0.1.0" - is-path-inside "^1.0.0" - -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== - -is-my-json-valid@^2.12.4: - version "2.20.6" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz#a9d89e56a36493c77bda1440d69ae0dc46a08387" - integrity sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^5.0.0" - xtend "^4.0.0" - -is-npm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= - dependencies: - path-is-inside "^1.0.1" - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-property@^1.0.0, is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isemail@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" - integrity sha1-vgPfjMPineTSxd9lASY/H6RZXpo= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -joi@^6.10.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" - integrity sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY= - dependencies: - hoek "2.x.x" - isemail "1.x.x" - moment "2.x.x" - topo "1.x.x" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsonpointer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072" - integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg== - -jsonwebtoken@7.1.9: - version "7.1.9" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.1.9.tgz#847804e5258bec5a9499a8dc4a5e7a3bae08d58a" - integrity sha1-hHgE5SWL7FqUmajcSl56O64I1Yo= - dependencies: - joi "^6.10.1" - jws "^3.1.3" - lodash.once "^4.0.0" - ms "^0.7.1" - xtend "^4.0.1" - -jsonwebtoken@^5.0.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-5.7.0.tgz#1c90f9a86ce5b748f5f979c12b70402b4afcddb4" - integrity sha1-HJD5qGzlt0j1+XnBK3BAK0r83bQ= - dependencies: - jws "^3.0.0" - ms "^0.7.1" - xtend "^4.0.1" - -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.0.0, jws@^3.1.3: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - -kareem@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.2.tgz#78c4508894985b8d38a0dc15e1a8e11078f2ca93" - integrity sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.0.4, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -latest-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= - dependencies: - package-json "^4.0.0" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= - -liquid-json@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/liquid-json/-/liquid-json-0.3.1.tgz#9155a18136d8a6b2615e5f16f9a2448ab6b50eea" - integrity sha1-kVWhgTbYprJhXl8W+aJEira1Duo= - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -lodash.escaperegexp@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" - integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= - -lodash.foreach@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= - -lodash.get@^4.0.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.mergewith@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" - integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= - -lodash@4.17.10: - version "4.17.10" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== - -lodash@4.17.9: - version "4.17.9" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.9.tgz#9c056579af0bdbb4322e23c836df13ef2b271cb7" - integrity sha512-vuRLquvot5sKUldMBumG0YqLvX6m/RGBBOmqb3CWR/MC/QvvD1cTH1fOqxz2FJAQeoExeUdX5Gu9vP2EP6ik+Q== - -lodash@^4.17.10, lodash@^4.17.14: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -lodash@~3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= - -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -marked@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.4.0.tgz#9ad2c2a7a1791f10a852e0112f77b571dce10c66" - integrity sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memory-pager@^1.0.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" - integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -method-override@2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/method-override/-/method-override-2.3.5.tgz#2cd5cdbff00c3673d7ae345119a812a5d95b8c8e" - integrity sha1-LNXNv/AMNnPXrjRRGagSpdlbjI4= - dependencies: - debug "~2.2.0" - methods "~1.1.1" - parseurl "~1.3.0" - vary "~1.0.1" - -methods@1.1.2, methods@~1.1.1, methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== - -mime-format@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mime-format/-/mime-format-2.0.0.tgz#e29f8891e284d78270246f0050d6834bdbbe1332" - integrity sha1-4p+IkeKE14JwJG8AUNaDS9u+EzI= - dependencies: - charset "^1.0.0" - -mime-types@2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== - dependencies: - mime-db "~1.33.0" - -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.6, mime-types@~2.1.7: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" - integrity sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM= - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -moment@2.x.x: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - -mongodb@3.6.6: - version "3.6.6" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.6.tgz#92e3658f45424c34add3003e3046c1535c534449" - integrity sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w== - dependencies: - bl "^2.2.1" - bson "^1.1.4" - denque "^1.4.1" - optional-require "^1.0.2" - safe-buffer "^5.1.2" - optionalDependencies: - saslprep "^1.0.0" - -mongoose-legacy-pluralize@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" - integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ== - -mongoose-unique-validator@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mongoose-unique-validator/-/mongoose-unique-validator-3.1.0.tgz#10d6fa10ccf5515461e3b5693f193d227546d60b" - integrity sha512-UsBBlFapip8gc8x1h+nLWnkOy+GTy9Z+zmTyZ35icLV3EoLIVz180vJzepfMM9yBy2AJh+maeuoM8CWtqejGUg== - dependencies: - lodash.foreach "^4.1.0" - lodash.get "^4.0.2" - lodash.merge "^4.6.2" - -mongoose@5.12.5: - version "5.12.5" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.12.5.tgz#70d11d3e68a3aeeb6960262633e1ba80cb620385" - integrity sha512-VVoqiELZcoI2HhHDuPpfN3qmExrtIeXSWNb1nihf4w1SJoWGXilU/g2cQgeeSMc2vAHSZd5Nv2sNPvbZHFw+pg== - dependencies: - "@types/mongodb" "^3.5.27" - bson "^1.1.4" - kareem "2.3.2" - mongodb "3.6.6" - mongoose-legacy-pluralize "1.0.2" - mpath "0.8.3" - mquery "3.2.5" - ms "2.1.2" - regexp-clone "1.0.0" - safe-buffer "5.2.1" - sift "7.0.1" - sliced "1.0.1" - -morgan@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.7.0.tgz#eb10ca8e50d1abe0f8d3dad5c0201d052d981c62" - integrity sha1-6xDKjlDRq+D409rVwCAdBS2YHGI= - dependencies: - basic-auth "~1.0.3" - debug "~2.2.0" - depd "~1.1.0" - on-finished "~2.3.0" - on-headers "~1.0.1" - -mpath@0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.8.3.tgz#828ac0d187f7f42674839d74921970979abbdd8f" - integrity sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA== - -mquery@3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.2.5.tgz#8f2305632e4bb197f68f60c0cffa21aaf4060c51" - integrity sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A== - dependencies: - bluebird "3.5.1" - debug "3.1.0" - regexp-clone "^1.0.0" - safe-buffer "5.1.2" - sliced "1.0.1" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^0.7.1: - version "0.7.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" - integrity sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8= - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nan@^2.12.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -negotiator@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" - integrity sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g= - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -newman@^3.8.2: - version "3.10.0" - resolved "https://registry.yarnpkg.com/newman/-/newman-3.10.0.tgz#24bb43963e25bb79a4fc158cd76bf20eaa179f06" - integrity sha512-8dr3kUedx/D4a/tiysvEjEQ+D+lLA/sgPASN33AiRyTKtdqzeVFuuBZYb3Jb+0TBd84Y3Qk8t24GuTY22HJN4g== - dependencies: - async "2.6.1" - cli-progress "1.8.0" - cli-table3 "0.4.0" - colors "1.3.0" - commander "2.16.0" - csv-parse "1.3.3" - eventemitter3 "3.1.0" - filesize "3.6.1" - handlebars "4.0.11" - lodash "4.17.9" - mkdirp "0.5.1" - parse-json "4.0.0" - postman-collection "3.1.1" - postman-collection-transformer "2.5.10" - postman-request "2.86.1-postman.1" - postman-runtime "7.2.0" - pretty-ms "3.2.0" - semver "5.5.0" - serialised-error "1.1.3" - shelljs "0.8.2" - word-wrap "1.2.3" - xmlbuilder "10.0.0" - -node-oauth1@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/node-oauth1/-/node-oauth1-1.2.2.tgz#fffb2813a88c2770711332ad0e5487b4927644a4" - integrity sha512-f2XC7Y68wJq6+s+LJn/yUq5Gqg9Y9zwIz2zY6vUyS8xzawnSWhXKOMJepLwvptjPl8IjVxtWh7iI9dbdKGSw4g== - dependencies: - crypto-js "3.1.9-1" - -node-uuid@~1.4.7: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - integrity sha1-sEDrCSOWivq/jTL7HxfxFn/auQc= - -nodemon@^1.11.0: - version "1.19.4" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.4.tgz#56db5c607408e0fdf8920d2b444819af1aae0971" - integrity sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ== - dependencies: - chokidar "^2.1.8" - debug "^3.2.6" - ignore-by-default "^1.0.1" - minimatch "^3.0.4" - pstree.remy "^1.1.7" - semver "^5.7.1" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.2" - update-notifier "^2.5.0" - -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -oauth-sign@~0.8.0, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-hash@^1.1.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" - integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optional-require@^1.0.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/optional-require/-/optional-require-1.1.8.tgz#16364d76261b75d964c482b2406cb824d8ec44b7" - integrity sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA== - dependencies: - require-at "^1.0.6" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -package-json@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" - integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= - dependencies: - got "^6.7.1" - registry-auth-token "^3.0.1" - registry-url "^3.0.3" - semver "^5.1.0" - -parse-json@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-ms@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" - integrity sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0= - -parseurl@~1.3.0, parseurl@~1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -passport-local@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" - integrity sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4= - dependencies: - passport-strategy "1.x.x" - -passport-strategy@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" - integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= - -passport@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.3.2.tgz#9dd009f915e8fe095b0124a01b8f82da07510102" - integrity sha1-ndAJ+RXo/glbASSgG4+C2gdRAQI= - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -pause@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" - integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss@^6.0.14: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -postman-collection-transformer@2.5.10: - version "2.5.10" - resolved "https://registry.yarnpkg.com/postman-collection-transformer/-/postman-collection-transformer-2.5.10.tgz#cecf07b7cdac58b09d7a3e7eae0af3e47c6f7cc4" - integrity sha512-2Pm0Z6v9IfqYhZciYW9i3ZUqOkLIf/AO2Ll389G0LlHJ/qg82sFhL0V4wUI1JQE6nd4eLBiUwhdPEPlHPQIWjQ== - dependencies: - commander "2.16.0" - inherits "2.0.3" - intel "1.2.0" - lodash "4.17.10" - semver "5.5.0" - strip-json-comments "2.0.1" - -postman-collection@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postman-collection/-/postman-collection-3.1.1.tgz#9042c1e7891f3f319566fd05f6f2aeeb51bc8d45" - integrity sha512-0Q9BpVVdquv4Wf/Kpvf8LgLADsnZW8g4lGouBncD2pn+mHzL72oWJmD9/kV56wp4SuQl0a1OZNuUYkK9fYPxOA== - dependencies: - escape-html "1.0.3" - file-type "3.9.0" - http-reasons "0.1.0" - iconv-lite "0.4.22" - liquid-json "0.3.1" - lodash "4.17.10" - marked "0.4.0" - mime-format "2.0.0" - mime-types "2.1.18" - postman-url-encoder "1.0.1" - sanitize-html "1.18.2" - semver "5.5.0" - uuid "3.3.2" - -postman-request@2.86.1-postman.1: - version "2.86.1-postman.1" - resolved "https://registry.yarnpkg.com/postman-request/-/postman-request-2.86.1-postman.1.tgz#bc43b753771e8fdcbad95f1436881f81e6c5bef2" - integrity sha512-HzzRbCLcOItaFhhvYiv0/LWShEZ4Lir8ZCL2OiQ8pkpirKM9u7BUQ4OgqNzTExt3m8NWg60f19eQ0hk1cNphLg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - postman-url-encoder "1.0.1" - qs "~6.5.1" - safe-buffer "^5.1.1" - stream-length "^1.0.2" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -postman-runtime@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/postman-runtime/-/postman-runtime-7.2.0.tgz#9d7796fd6981826b8abb887a02370059a02a04e2" - integrity sha512-penzRSjXckHeGXMP6NxvJVLbhxDa47Uei8RIbzf4gEV+1qTZ5qp9QppW2yWPNb5SSW1Z113t6LGKlpVR+plZMQ== - dependencies: - async "2.6.1" - aws4 "1.7.0" - btoa "1.2.1" - crypto-js "3.1.9-1" - eventemitter3 "3.1.0" - hawk "6.0.2" - http-reasons "0.1.0" - httpntlm "1.7.6" - inherits "2.0.3" - lodash "4.17.10" - node-oauth1 "1.2.2" - postman-collection "3.1.1" - postman-request "2.86.1-postman.1" - postman-sandbox "3.1.1" - resolve-from "4.0.0" - serialised-error "1.1.3" - uuid "3.3.2" - -postman-sandbox@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postman-sandbox/-/postman-sandbox-3.1.1.tgz#31ed0a97e9a2c803166a2080fe879a3377470e0f" - integrity sha512-bch46g1LfPnCeCTYQXKlYDmrnTljAPS74a12z5XCS2lJ4veIitX8y4b+mBZSxzMZ05tIZrUTDv+XoyZbRlpagw== - dependencies: - inherits "2.0.3" - lodash "4.17.10" - uuid "3.3.2" - uvm "1.7.3" - -postman-url-encoder@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postman-url-encoder/-/postman-url-encoder-1.0.1.tgz#a094a42e9415ff0bbfdce0eaa8e6011d449ee83c" - integrity sha1-oJSkLpQV/wu/3ODqqOYBHUSe6Dw= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -pretty-ms@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-3.2.0.tgz#87a8feaf27fc18414d75441467d411d6e6098a25" - integrity sha512-ZypexbfVUGTFxb0v+m1bUyy92DHe5SyYlnyY0msyms5zd3RwyvNgyxZZsXXgoyzlxjx5MiqtXUdhUfvQbe0A2Q== - dependencies: - parse-ms "^1.0.0" - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -proxy-addr@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.0.10.tgz#0d40a82f801fc355567d2ecb65efe3f077f121c5" - integrity sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU= - dependencies: - forwarded "~0.1.0" - ipaddr.js "1.0.5" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -pstree.remy@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" - integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -qs@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" - integrity sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc= - -qs@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.1.0.tgz#ec1d1626b24278d99f0fdf4549e524e24eceeb26" - integrity sha1-7B0WJrJCeNmfD99FSeUk4k7O6yY= - -qs@~6.0.2: - version "6.0.4" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.0.4.tgz#51019d84720c939b82737e84556a782338ecea7b" - integrity sha1-UQGdhHIMk5uCc36EVWp4Izjs6ns= - -qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -range-parser@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" - integrity sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU= - -raw-body@~2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" - integrity sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q= - dependencies: - bytes "2.4.0" - iconv-lite "0.4.13" - unpipe "1.0.0" - -rc@^1.0.1, rc@^1.1.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.2, readable-stream@^2.3.5: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - integrity sha1-j5A0HmilPMySh4jaz80Rs265t44= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp-clone@1.0.0, regexp-clone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-1.0.0.tgz#222db967623277056260b992626354a04ce9bf63" - integrity sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw== - -registry-auth-token@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" - integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A== - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= - dependencies: - rc "^1.0.1" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.5.2, repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -request@2.69.0: - version "2.69.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.69.0.tgz#cf91d2e000752b1217155c005241911991a2346a" - integrity sha1-z5HS4AB1KxIXFVwAUkGRGZGiNGo= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - bl "~1.0.0" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~1.0.0-rc3" - har-validator "~2.0.6" - hawk "~3.1.0" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - node-uuid "~1.4.7" - oauth-sign "~0.8.0" - qs "~6.0.2" - stringstream "~0.0.4" - tough-cookie "~2.2.0" - tunnel-agent "~0.4.1" - -require-at@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a" - integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g== - -resolve-from@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.1.6: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= - dependencies: - align-text "^0.1.1" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sanitize-html@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.2.tgz#61877ba5a910327e42880a28803c2fbafa8e4642" - integrity sha512-52ThA+Z7h6BnvpSVbURwChl10XZrps5q7ytjTwWcIe9bmJwnVP6cpEVK2NvDOUhGupoqAvNbUz3cpnJDp4+/pg== - dependencies: - chalk "^2.3.0" - htmlparser2 "^3.9.0" - lodash.clonedeep "^4.5.0" - lodash.escaperegexp "^4.1.2" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.mergewith "^4.6.0" - postcss "^6.0.14" - srcset "^1.0.0" - xtend "^4.0.0" - -saslprep@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" - integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== - dependencies: - sparse-bitfield "^3.0.3" - -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= - dependencies: - semver "^5.0.3" - -semver@5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - -semver@^5.0.3, semver@^5.1.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -send@0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.13.1.tgz#a30d5f4c82c8a9bae9ad00a1d9b1bdbe6f199ed7" - integrity sha1-ow1fTILIqbrprQCh2bG9vm8Zntc= - dependencies: - debug "~2.2.0" - depd "~1.1.0" - destroy "~1.0.4" - escape-html "~1.0.3" - etag "~1.7.0" - fresh "0.3.0" - http-errors "~1.3.1" - mime "1.3.4" - ms "0.7.1" - on-finished "~2.3.0" - range-parser "~1.0.3" - statuses "~1.2.1" - -send@0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" - integrity sha1-dl52B8gFVFK7pvCwUllTUJhgNt4= - dependencies: - debug "~2.2.0" - depd "~1.1.0" - destroy "~1.0.4" - escape-html "~1.0.3" - etag "~1.7.0" - fresh "0.3.0" - http-errors "~1.3.1" - mime "1.3.4" - ms "0.7.1" - on-finished "~2.3.0" - range-parser "~1.0.3" - statuses "~1.2.1" - -serialised-error@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/serialised-error/-/serialised-error-1.1.3.tgz#8a4c466b29c26ff11016eaf1b5fa2b87ca4cd8b5" - integrity sha512-vybp3GItaR1ZtO2nxZZo8eOo7fnVaNtP3XE2vJKgzkKR2bagCkdJ1EpYYhEMd3qu/80DwQk9KjsNSxE3fXWq0g== - dependencies: - object-hash "^1.1.2" - stack-trace "0.0.9" - uuid "^3.0.0" - -serve-static@~1.10.2: - version "1.10.3" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" - integrity sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU= - dependencies: - escape-html "~1.0.3" - parseurl "~1.3.1" - send "0.13.2" - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shelljs@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -sift@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08" - integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g== - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - -sliced@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" - integrity sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E= - -slug@0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/slug/-/slug-0.9.1.tgz#af08f608a7c11516b61778aa800dce84c518cfda" - integrity sha1-rwj2CKfBFRa2F3iqgA3OhMUYz9o= - dependencies: - unicode ">= 0.3.1" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg== - dependencies: - hoek "4.x.x" - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" - -source-map@^0.5.6, source-map@~0.5.1: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sparse-bitfield@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" - integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= - dependencies: - memory-pager "^1.0.2" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -srcset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef" - integrity sha1-pWad4StC87HV6D7QPHEEb8SPQe8= - dependencies: - array-uniq "^1.0.2" - number-is-nan "^1.0.0" - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -stack-trace@0.0.9: - version "0.0.9" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" - integrity sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU= - -stack-trace@~0.0.9: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -statuses@1, "statuses@>= 1.2.1 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -statuses@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" - integrity sha1-3e1FzBglbVHtQK7BQkidXGECbSg= - -stream-length@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stream-length/-/stream-length-1.0.2.tgz#8277f3cbee49a4daabcfdb4e2f4a9b5e9f2c9f00" - integrity sha1-gnfzy+5JpNqrz9tOL0qbXp8snwA= - dependencies: - bluebird "^2.6.2" - -strftime@~0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/strftime/-/strftime-0.10.1.tgz#108af1176a7d5252cfbddbdb2af044dfae538389" - integrity sha512-nVvH6JG8KlXFPC0f8lojLgEsPA18lRpLZ+RrJh/NkQV2tqOgZfbas8gcU8SFgnnqR3rWzZPYu6N2A3xzs/8rQg== - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4: - version "0.0.6" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" - integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA== - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-json-comments@2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -symbol@~0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/symbol/-/symbol-0.3.1.tgz#b6f9a900d496a57f02408f22198c109dda063041" - integrity sha1-tvmpANSWpX8CQI8iGYwQndoGMEE= - -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= - dependencies: - execa "^0.7.0" - -timed-out@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -topo@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" - integrity sha1-6ddRYV0buH3IZdsYL6HKCl71NtU= - dependencies: - hoek "2.x.x" - -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== - dependencies: - nopt "~1.0.10" - -tough-cookie@~2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.2.2.tgz#c83a1830f4e5ef0b93ef2a3488e724f8de016ac7" - integrity sha1-yDoYMPTl7wuT7yo0iOck+N4Basc= - -tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== - dependencies: - punycode "^1.4.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - integrity sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us= - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-is@~1.6.11, type-is@~1.6.6: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -uglify-js@^2.6: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= - -uid-safe@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.0.0.tgz#a7f3c6ca64a1f6a5d04ec0ef3e4c3d5367317137" - integrity sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc= - dependencies: - base64-url "1.2.1" - -undefsafe@^2.0.2: - version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" - integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== - -underscore@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= - -underscore@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" - integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk= - -"unicode@>= 0.3.1": - version "13.0.0" - resolved "https://registry.yarnpkg.com/unicode/-/unicode-13.0.0.tgz#0775fe86cdbb1fa30e8d060afe194f71aa0c5306" - integrity sha512-osNPLT4Lqna/sV6DQikrB8m4WxR61/k0fnhfKnkPGcZImczW3IysRXvWxfdqGUjh0Ju2o/tGGgu46mlfc/cpZw== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= - dependencies: - crypto-random-string "^1.0.0" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -update-notifier@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" - integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== - dependencies: - boxen "^1.2.1" - chalk "^2.0.1" - configstore "^3.0.0" - import-lazy "^2.1.0" - is-ci "^1.0.10" - is-installed-globally "^0.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -utcstring@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/utcstring/-/utcstring-0.1.0.tgz#430fd510ab7fc95b5d5910c902d79880c208436b" - integrity sha1-Qw/VEKt/yVtdWRDJAteYgMIIQ2s= - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -utils-merge@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" - integrity sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg= - -uuid@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -uuid@^3.0.0, uuid@^3.1.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uvm@1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/uvm/-/uvm-1.7.3.tgz#57b37b218a158fa5c059de8527cd67ab64d82663" - integrity sha512-aKnLDcsr/qSYyiF9p049Kqatk/tHxT/gNanpbDzmdQ+XYo0E8lkCYwf478daiu8rXE3+TznBB8Sw/TKakJ6H1A== - dependencies: - circular-json "0.3.1" - inherits "2.0.3" - lodash "4.17.10" - uuid "3.2.1" - -vary@^1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vary@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" - integrity sha1-meSYFWaihhGN+yuBc1ffeZM3bRA= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== - dependencies: - string-width "^2.1.1" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= - -word-wrap@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^2.0.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= - -xmlbuilder@10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-10.0.0.tgz#c64e52f8ae097fe5fd46d1c38adaade071ee1b55" - integrity sha512-7RWHlmF1yU/E++BZkRQTEv8ZFAhZ+YHINUAxiZ5LQTKRQq//igpiY8rh7dJqPzgb/IzeC5jH9P7OaCERfM9DwA== - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" diff --git a/.framework/node/charts/.helmignore b/.framework/node/charts/.helmignore deleted file mode 100644 index 0e8a0eb..0000000 --- a/.framework/node/charts/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/.framework/node/charts/Chart.yaml b/.framework/node/charts/Chart.yaml deleted file mode 100644 index b2beb19..0000000 --- a/.framework/node/charts/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: app -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" diff --git a/.framework/node/charts/templates/_helpers.yml b/.framework/node/charts/templates/_helpers.yml deleted file mode 100644 index 49515f2..0000000 --- a/.framework/node/charts/templates/_helpers.yml +++ /dev/null @@ -1,24 +0,0 @@ -{{- define "anythink-tenant.backendHost" -}} - https://{{- .Release.Namespace }}-api. - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.stagingBackendHost }} - {{- else }} - {{- .Values.productionBackendHost }} - {{- end }} -{{- end }} - -{{- define "anythink-tenant.backendRepository" -}} - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.backend.image.stagingRepository }} - {{- else }} - {{- .Values.backend.image.repository }} - {{- end }} -{{- end }} - -{{- define "anythink-tenant.frontendRepository" -}} - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.frontend.image.stagingRepository }} - {{- else }} - {{- .Values.frontend.image.repository }} - {{- end }} -{{- end }} diff --git a/.framework/node/charts/templates/anythink-backend-deployment.yaml b/.framework/node/charts/templates/anythink-backend-deployment.yaml deleted file mode 100644 index 260d252..0000000 --- a/.framework/node/charts/templates/anythink-backend-deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.backend.serviceName }} - name: {{ .Values.backend.serviceName }} -spec: - replicas: {{ .Values.backend.replicaCount }} - selector: - matchLabels: - app: {{ .Values.backend.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.backend.serviceName }} - date: {{ now | unixEpoch | quote }} - spec: - containers: - - args: - - sh - - -c - - "yarn seeds && yarn start" - env: - - name: MONGODB_URI - value: "{{ .Values.database.connectionProtocol }}{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}/{{ .Values.database.databaseName }}" - - name: NODE_ENV - value: development - - name: PORT - value: "{{ .Values.backend.containerPort }}" - image: "{{ include "anythink-tenant.backendRepository" .}}:{{ .Values.backend.image.tag }}" - imagePullPolicy: {{ .Values.backend.image.pullPolicy }} - name: {{ .Values.backend.serviceName }} - ports: - - containerPort: {{ .Values.backend.containerPort }} - name: http - protocol: TCP - startupProbe: - httpGet: - path: /health - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: /health - port: http - readinessProbe: - httpGet: - path: /health - port: http - resources: - {{- toYaml .Values.backend.resources | nindent 12 }} - restartPolicy: Always diff --git a/.framework/node/charts/templates/anythink-backend-service.yaml b/.framework/node/charts/templates/anythink-backend-service.yaml deleted file mode 100644 index 21bb516..0000000 --- a/.framework/node/charts/templates/anythink-backend-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: {{ .Values.backend.serviceName }} - name: {{ .Values.backend.serviceName }} -spec: - ports: - - name: "{{ .Values.backend.containerPort }}" - port: {{ .Values.backend.containerPort }} - targetPort: {{ .Values.backend.containerPort }} - selector: - app: {{ .Values.backend.serviceName }} diff --git a/.framework/node/charts/templates/anythink-frontend-deployment.yaml b/.framework/node/charts/templates/anythink-frontend-deployment.yaml deleted file mode 100644 index f9be249..0000000 --- a/.framework/node/charts/templates/anythink-frontend-deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.frontend.serviceName }} - name: {{ .Values.frontend.serviceName }} -spec: - replicas: {{ .Values.frontend.replicaCount }} - selector: - matchLabels: - app: {{ .Values.frontend.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.frontend.serviceName }} - date: {{ now | unixEpoch | quote }} - spec: - containers: - - args: - - sh - - -c - - yarn start - env: - - name: NODE_ENV - value: development - - name: PORT - value: "{{ .Values.frontend.containerPort }}" - - name: REACT_APP_BACKEND_URL - value: {{ include "anythink-tenant.backendHost" .}} - image: "{{ include "anythink-tenant.frontendRepository" .}}:{{ .Values.frontend.image.tag }}" - imagePullPolicy: {{ .Values.frontend.image.pullPolicy }} - name: {{ .Values.frontend.serviceName }} - ports: - - containerPort: {{ .Values.frontend.containerPort }} - name: http - protocol: TCP - startupProbe: - httpGet: - path: / - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: / - port: http - readinessProbe: - httpGet: - path: / - port: http - resources: - {{- toYaml .Values.frontend.resources | nindent 12 }} - restartPolicy: Always diff --git a/.framework/node/charts/templates/anythink-frontend-service.yaml b/.framework/node/charts/templates/anythink-frontend-service.yaml deleted file mode 100644 index 217f8c5..0000000 --- a/.framework/node/charts/templates/anythink-frontend-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: {{ .Values.frontend.serviceName }} - name: {{ .Values.frontend.serviceName }} -spec: - ports: - - name: "{{ .Values.frontend.containerPort }}" - port: {{ .Values.frontend.containerPort }} - targetPort: {{ .Values.frontend.containerPort }} - selector: - app: {{ .Values.frontend.serviceName }} diff --git a/.framework/node/charts/templates/database-deployment.yaml b/.framework/node/charts/templates/database-deployment.yaml deleted file mode 100644 index 62deccc..0000000 --- a/.framework/node/charts/templates/database-deployment.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if .Values.database.deploy }} -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.database.serviceName }} - name: {{ .Values.database.serviceName }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.database.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.database.serviceName }} - spec: - containers: - - image: "{{ .Values.database.image.repository }}:{{ .Values.database.image.tag }}" - name: {{ .Values.database.serviceName }} - imagePullPolicy: {{ .Values.database.image.pullPolicy }} - ports: - - containerPort: {{ .Values.database.containerPort }} - resources: {} - volumeMounts: - - mountPath: /data/db - name: {{ .Values.database.serviceName }}-0 - restartPolicy: Always - volumes: - - name: {{ .Values.database.serviceName }}-0 - persistentVolumeClaim: - claimName: {{ .Values.database.serviceName }}-0 -{{- end }} diff --git a/.framework/node/charts/templates/database-pvc.yaml b/.framework/node/charts/templates/database-pvc.yaml deleted file mode 100644 index 88517f3..0000000 --- a/.framework/node/charts/templates/database-pvc.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app: {{ .Values.database.serviceName }}-0 - name: {{ .Values.database.serviceName }}-0 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Mi diff --git a/.framework/node/charts/templates/database-service.yaml b/.framework/node/charts/templates/database-service.yaml deleted file mode 100644 index 80b47d3..0000000 --- a/.framework/node/charts/templates/database-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: {{ .Values.database.serviceName }} - name: {{ .Values.database.serviceName }} -spec: - ports: - - name: "{{ .Values.database.servicePort }}" - port: {{ .Values.database.servicePort }} - targetPort: {{ .Values.database.servicePort }} - selector: - app: {{ .Values.database.serviceName }} diff --git a/.framework/node/charts/values.yaml b/.framework/node/charts/values.yaml deleted file mode 100644 index 1fa785d..0000000 --- a/.framework/node/charts/values.yaml +++ /dev/null @@ -1,68 +0,0 @@ -clusterEnv: "" -productionBackendHost: "prod.anythink.market" -stagingBackendHost: "staging.anythink.market" - -backend: - serviceName: anythink-backend - containerPort: 3000 - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/anythink-backend - stagingRepository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/staging-anythink-backend - pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 128Mi - -frontend: - serviceName: anythink-frontend - containerPort: 3001 - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/anythink-frontend - stagingRepository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/staging-anythink-frontend - pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - resources: - limits: - cpu: 600m - memory: 768Mi - requests: - cpu: 100m - memory: 128Mi - -database: - deploy: true - serviceName: mongodb-node - containerPort: 27017 - servicePort: 27017 - connectionProtocol: mongodb:// - databaseName: anythink-market - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: mongo - pullPolicy: IfNotPresent - tag: "latest" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi diff --git a/.framework/node/docker-compose.yml b/.framework/node/docker-compose.yml deleted file mode 100644 index c233da8..0000000 --- a/.framework/node/docker-compose.yml +++ /dev/null @@ -1,58 +0,0 @@ -version: "3.8" -services: - anythink-backend-node: - build: ./backend - container_name: anythink-backend-node - command: sh -c "cd backend && yarn install && /wait-for-it.sh mongodb-node:27017 -q -t 60 && yarn dev" - - environment: - - NODE_ENV=development - - PORT=3000 - - MONGODB_URI=mongodb://mongodb-node:27017/anythink-market - - GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN=${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN} - working_dir: /usr/src - volumes: - - ./:/usr/src/ - - /usr/src/backend/node_modules - ports: - - "3000:3000" - depends_on: - - "mongodb-node" - - anythink-frontend-react: - build: ./frontend - container_name: anythink-frontend-react - command: sh -c "cd frontend && yarn install && /wait-for-it.sh anythink-backend-node:3000 -t 120 --strict -- curl --head -X GET --retry 30 --retry-connrefused --retry-delay 1 anythink-backend-node:3000/api/ping && yarn start" - environment: - - NODE_ENV=development - - PORT=3001 - - REACT_APP_BACKEND_URL=${CODESPACE_BACKEND_URL:-http://localhost:3000} - - WDS_SOCKET_PORT=${CODESPACE_WDS_SOCKET_PORT:-3001} - working_dir: /usr/src - volumes: - - ./:/usr/src/ - - /usr/src/frontend/node_modules - ports: - - "3001:3001" - depends_on: - - "anythink-backend-node" - - mongodb-node: - container_name: mongodb-node - restart: always - image: mongo - logging: - driver: none - volumes: - - ~/mongo/data:/data/db - ports: - - '27017:27017' - - anythink-ack: - image: public.ecr.aws/v0a2l7y2/wilco/anythink-ack:latest - container_name: anythink-ack - environment: - - GITHUB_TOKEN=$GITHUB_TOKEN - - CODESPACE_NAME=$CODESPACE_NAME - depends_on: - - "anythink-frontend-react" diff --git a/.framework/python/.devcontainer/devcontainer.json b/.framework/python/.devcontainer/devcontainer.json deleted file mode 100644 index 171e2d2..0000000 --- a/.framework/python/.devcontainer/devcontainer.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Anythink Development Container", - "image": "public.ecr.aws/v0a2l7y2/wilco/anythink-devcontainer:latest" -} diff --git a/.framework/python/backend/.dockerignore b/.framework/python/backend/.dockerignore deleted file mode 100644 index 238473f..0000000 --- a/.framework/python/backend/.dockerignore +++ /dev/null @@ -1,20 +0,0 @@ -__pycache__ -*.pyc -*.pyo -*.pyd -.Python -.env* -pip-log.txt -pip-delete-this-directory.txt -.tox -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*,cover -*.log -.git* -scripts -postman -./postgres-data diff --git a/.framework/python/backend/.gitignore b/.framework/python/backend/.gitignore deleted file mode 100644 index ab61e76..0000000 --- a/.framework/python/backend/.gitignore +++ /dev/null @@ -1,110 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ - -.idea/ -.vscode/ - -# Project -postgres-data diff --git a/.framework/python/backend/Dockerfile b/.framework/python/backend/Dockerfile deleted file mode 100644 index 7dfd3f3..0000000 --- a/.framework/python/backend/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM public.ecr.aws/v0a2l7y2/wilco/anythink-backend-python:latest - diff --git a/.framework/python/backend/Dockerfile.aws b/.framework/python/backend/Dockerfile.aws deleted file mode 100644 index 3ee3974..0000000 --- a/.framework/python/backend/Dockerfile.aws +++ /dev/null @@ -1,15 +0,0 @@ -FROM python:3.9.13 - -ENV VIRTUAL_ENV=/opt/venv -RUN python3 -m venv $VIRTUAL_ENV -ENV PATH="$VIRTUAL_ENV/bin:$PATH" - -RUN pip install poetry==1.2.0 - -# Pre-install poetry packages -WORKDIR /usr/src -COPY backend ./backend -COPY .wilco ./.wilco -WORKDIR /usr/src/backend -RUN poetry install -RUN poetry export -f "requirements.txt" --without-hashes --with-credentials > "requirements.txt" diff --git a/.framework/python/backend/LICENSE b/.framework/python/backend/LICENSE deleted file mode 100644 index 173d6d0..0000000 --- a/.framework/python/backend/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Nik Sidnev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -SELLERS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/.framework/python/backend/README.md b/.framework/python/backend/README.md deleted file mode 100644 index 3a6fc73..0000000 --- a/.framework/python/backend/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Web routes -========== - -All routes are available on `/docs` or `/redoc` paths with Swagger or ReDoc. - -Project structure -================= - -Files related to application are in the `app` or `tests` directories. Application parts are: - - app - ├── api - web related stuff. - │   ├── dependencies - dependencies for routes definition. - │   ├── errors - definition of error handlers. - │   └── routes - web routes. - ├── core - application configuration, startup events, logging. - ├── db - db related stuff. - │   ├── migrations - manually written alembic migrations. - │   └── repositories - all crud stuff. - ├── models - pydantic models for this application. - │   ├── domain - main models that are used almost everywhere. - │   └── schemas - schemas for using in web routes. - ├── resources - strings that are used in web responses. - ├── services - logic that is not just crud related. - └── main.py - FastAPI application creation and configuration. - -Project structure -================= - -Project dependencies are managed by poetry (https://python-poetry.org), using venv (https://docs.python.org/3/library/venv.html). diff --git a/.framework/python/backend/alembic.ini b/.framework/python/backend/alembic.ini deleted file mode 100644 index 2c43e60..0000000 --- a/.framework/python/backend/alembic.ini +++ /dev/null @@ -1,36 +0,0 @@ -[alembic] -script_location = ./app/db/migrations - -[loggers] -keys = root,sqlalchemy,alembic - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARN -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARN -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = INFO -handlers = -qualname = alembic - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/.framework/python/backend/app/__init__.py b/.framework/python/backend/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/api/__init__.py b/.framework/python/backend/app/api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/api/dependencies/__init__.py b/.framework/python/backend/app/api/dependencies/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/api/dependencies/authentication.py b/.framework/python/backend/app/api/dependencies/authentication.py deleted file mode 100644 index dbc8d48..0000000 --- a/.framework/python/backend/app/api/dependencies/authentication.py +++ /dev/null @@ -1,111 +0,0 @@ -# noqa:WPS201 -from typing import Callable, Optional - -from fastapi import Depends, HTTPException, Security -from fastapi.security import APIKeyHeader -from starlette import requests, status -from starlette.exceptions import HTTPException as StarletteHTTPException - -from app.api.dependencies.database import get_repository -from app.core.config import get_app_settings -from app.core.settings.app import AppSettings -from app.db.errors import EntityDoesNotExist -from app.db.repositories.users import UsersRepository -from app.models.domain.users import User -from app.resources import strings -from app.services import jwt - -HEADER_KEY = "Authorization" - - -class RWAPIKeyHeader(APIKeyHeader): - async def __call__( # noqa: WPS610 - self, - request: requests.Request, - ) -> Optional[str]: - try: - return await super().__call__(request) - except StarletteHTTPException as original_auth_exc: - raise HTTPException( - status_code=original_auth_exc.status_code, - detail=strings.AUTHENTICATION_REQUIRED, - ) - - -def get_current_user_authorizer(*, required: bool = True) -> Callable: # type: ignore - return _get_current_user if required else _get_current_user_optional - - -def _get_authorization_header_retriever( - *, - required: bool = True, -) -> Callable: # type: ignore - return _get_authorization_header if required else _get_authorization_header_optional - - -def _get_authorization_header( - api_key: str = Security(RWAPIKeyHeader(name=HEADER_KEY)), - settings: AppSettings = Depends(get_app_settings), -) -> str: - try: - token_prefix, token = api_key.split(" ") - except ValueError: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=strings.WRONG_TOKEN_PREFIX, - ) - if token_prefix != settings.jwt_token_prefix: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=strings.WRONG_TOKEN_PREFIX, - ) - - return token - - -def _get_authorization_header_optional( - authorization: Optional[str] = Security( - RWAPIKeyHeader(name=HEADER_KEY, auto_error=False), - ), - settings: AppSettings = Depends(get_app_settings), -) -> str: - if authorization: - return _get_authorization_header(authorization, settings) - - return "" - - -async def _get_current_user( - users_repo: UsersRepository = Depends(get_repository(UsersRepository)), - token: str = Depends(_get_authorization_header_retriever()), - settings: AppSettings = Depends(get_app_settings), -) -> User: - try: - username = jwt.get_username_from_token( - token, - str(settings.secret_key.get_secret_value()), - ) - except ValueError: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=strings.MALFORMED_PAYLOAD, - ) - - try: - return await users_repo.get_user_by_username(username=username) - except EntityDoesNotExist: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=strings.MALFORMED_PAYLOAD, - ) - - -async def _get_current_user_optional( - repo: UsersRepository = Depends(get_repository(UsersRepository)), - token: str = Depends(_get_authorization_header_retriever(required=False)), - settings: AppSettings = Depends(get_app_settings), -) -> Optional[User]: - if token: - return await _get_current_user(repo, token, settings) - - return None diff --git a/.framework/python/backend/app/api/dependencies/comments.py b/.framework/python/backend/app/api/dependencies/comments.py deleted file mode 100644 index 07073b7..0000000 --- a/.framework/python/backend/app/api/dependencies/comments.py +++ /dev/null @@ -1,37 +0,0 @@ -from typing import Optional - -from fastapi import Depends, HTTPException, Path -from starlette import status - -from app.api.dependencies import items, authentication, database -from app.db.errors import EntityDoesNotExist -from app.db.repositories.comments import CommentsRepository -from app.models.domain.items import Item -from app.models.domain.comments import Comment -from app.models.domain.users import User -from app.resources import strings - - -async def get_comment_by_id_from_path( - comment_id: int = Path(..., ge=1), - item: Item = Depends(items.get_item_by_slug_from_path), - user: Optional[User] = Depends( - authentication.get_current_user_authorizer(required=False), - ), - comments_repo: CommentsRepository = Depends( - database.get_repository(CommentsRepository), - ), -) -> Comment: - try: - return await comments_repo.get_comment_by_id( - comment_id=comment_id, - item=item, - user=user, - ) - except EntityDoesNotExist: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=strings.COMMENT_DOES_NOT_EXIST, - ) - - diff --git a/.framework/python/backend/app/api/dependencies/database.py b/.framework/python/backend/app/api/dependencies/database.py deleted file mode 100644 index cc91306..0000000 --- a/.framework/python/backend/app/api/dependencies/database.py +++ /dev/null @@ -1,30 +0,0 @@ -from typing import AsyncGenerator, Callable, Type - -from asyncpg.connection import Connection -from asyncpg.pool import Pool -from fastapi import Depends -from starlette.requests import Request - -from app.db.repositories.base import BaseRepository - - -def _get_db_pool(request: Request) -> Pool: - return request.app.state.pool - - -async def _get_connection_from_pool( - pool: Pool = Depends(_get_db_pool), -) -> AsyncGenerator[Connection, None]: - async with pool.acquire() as conn: - yield conn - - -def get_repository( - repo_type: Type[BaseRepository], -) -> Callable[[Connection], BaseRepository]: - def _get_repo( - conn: Connection = Depends(_get_connection_from_pool), - ) -> BaseRepository: - return repo_type(conn) - - return _get_repo diff --git a/.framework/python/backend/app/api/dependencies/items.py b/.framework/python/backend/app/api/dependencies/items.py deleted file mode 100644 index 8688c96..0000000 --- a/.framework/python/backend/app/api/dependencies/items.py +++ /dev/null @@ -1,59 +0,0 @@ -from typing import Optional - -from fastapi import Depends, HTTPException, Path, Query -from starlette import status - -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.database import get_repository -from app.db.errors import EntityDoesNotExist -from app.db.repositories.items import ItemsRepository -from app.models.domain.items import Item -from app.models.domain.users import User -from app.models.schemas.items import ( - DEFAULT_ITEMS_LIMIT, - DEFAULT_ITEMS_OFFSET, - ItemsFilters, -) -from app.resources import strings -from app.services.items import check_user_can_modify_item - - -def get_items_filters( - tag: Optional[str] = None, - seller: Optional[str] = None, - favorited: Optional[str] = None, - limit: int = Query(DEFAULT_ITEMS_LIMIT, ge=1), - offset: int = Query(DEFAULT_ITEMS_OFFSET, ge=0), -) -> ItemsFilters: - return ItemsFilters( - tag=tag, - seller=seller, - favorited=favorited, - limit=limit, - offset=offset, - ) - - -async def get_item_by_slug_from_path( - slug: str = Path(..., min_length=1), - user: Optional[User] = Depends(get_current_user_authorizer(required=False)), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> Item: - try: - return await items_repo.get_item_by_slug(slug=slug, requested_user=user) - except EntityDoesNotExist: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=strings.ITEM_DOES_NOT_EXIST_ERROR, - ) - - -def check_item_modification_permissions( - current_item: Item = Depends(get_item_by_slug_from_path), - user: User = Depends(get_current_user_authorizer()), -) -> None: - if not check_user_can_modify_item(current_item, user): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=strings.USER_IS_NOT_SELLER_OF_ITEM, - ) diff --git a/.framework/python/backend/app/api/dependencies/profiles.py b/.framework/python/backend/app/api/dependencies/profiles.py deleted file mode 100644 index db8f9b0..0000000 --- a/.framework/python/backend/app/api/dependencies/profiles.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Optional - -from fastapi import Depends, HTTPException, Path -from starlette.status import HTTP_404_NOT_FOUND - -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.database import get_repository -from app.db.errors import EntityDoesNotExist -from app.db.repositories.profiles import ProfilesRepository -from app.models.domain.profiles import Profile -from app.models.domain.users import User -from app.resources import strings - - -async def get_profile_by_username_from_path( - username: str = Path(..., min_length=1), - user: Optional[User] = Depends(get_current_user_authorizer(required=False)), - profiles_repo: ProfilesRepository = Depends(get_repository(ProfilesRepository)), -) -> Profile: - try: - return await profiles_repo.get_profile_by_username( - username=username, - requested_user=user, - ) - except EntityDoesNotExist: - raise HTTPException( - status_code=HTTP_404_NOT_FOUND, - detail=strings.USER_DOES_NOT_EXIST_ERROR, - ) diff --git a/.framework/python/backend/app/api/errors/__init__.py b/.framework/python/backend/app/api/errors/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/api/errors/http_error.py b/.framework/python/backend/app/api/errors/http_error.py deleted file mode 100644 index c503229..0000000 --- a/.framework/python/backend/app/api/errors/http_error.py +++ /dev/null @@ -1,7 +0,0 @@ -from fastapi import HTTPException -from starlette.requests import Request -from starlette.responses import JSONResponse - - -async def http_error_handler(_: Request, exc: HTTPException) -> JSONResponse: - return JSONResponse({"errors": [exc.detail]}, status_code=exc.status_code) diff --git a/.framework/python/backend/app/api/errors/validation_error.py b/.framework/python/backend/app/api/errors/validation_error.py deleted file mode 100644 index a85730c..0000000 --- a/.framework/python/backend/app/api/errors/validation_error.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Union - -from fastapi.exceptions import RequestValidationError -from fastapi.openapi.constants import REF_PREFIX -from fastapi.openapi.utils import validation_error_response_definition -from pydantic import ValidationError -from starlette.requests import Request -from starlette.responses import JSONResponse -from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY - - -async def http422_error_handler( - _: Request, - exc: Union[RequestValidationError, ValidationError], -) -> JSONResponse: - return JSONResponse( - {"errors": exc.errors()}, - status_code=HTTP_422_UNPROCESSABLE_ENTITY, - ) - - -validation_error_response_definition["properties"] = { - "errors": { - "title": "Errors", - "type": "array", - "items": {"$ref": "{0}ValidationError".format(REF_PREFIX)}, - }, -} diff --git a/.framework/python/backend/app/api/routes/__init__.py b/.framework/python/backend/app/api/routes/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/api/routes/api.py b/.framework/python/backend/app/api/routes/api.py deleted file mode 100644 index 7404d51..0000000 --- a/.framework/python/backend/app/api/routes/api.py +++ /dev/null @@ -1,17 +0,0 @@ -from fastapi import APIRouter - -from app.api.routes import authentication, comments, profiles, tags, users, ping -from app.api.routes.items import api as items - -router = APIRouter() -router.include_router(ping.router, prefix="/ping") -router.include_router(authentication.router, tags=["authentication"], prefix="/users") -router.include_router(users.router, tags=["users"], prefix="/user") -router.include_router(profiles.router, tags=["profiles"], prefix="/profiles") -router.include_router(items.router, tags=["items"]) -router.include_router( - comments.router, - tags=["comments"], - prefix="/items/{slug}/comments", -) -router.include_router(tags.router, tags=["tags"], prefix="/tags") diff --git a/.framework/python/backend/app/api/routes/authentication.py b/.framework/python/backend/app/api/routes/authentication.py deleted file mode 100644 index 35d7322..0000000 --- a/.framework/python/backend/app/api/routes/authentication.py +++ /dev/null @@ -1,97 +0,0 @@ -from fastapi import APIRouter, Body, Depends, HTTPException -from starlette.status import HTTP_201_CREATED, HTTP_400_BAD_REQUEST - -from app.api.dependencies.database import get_repository -from app.core.config import get_app_settings -from app.core.settings.app import AppSettings -from app.db.errors import EntityDoesNotExist -from app.db.repositories.users import UsersRepository -from app.models.schemas.users import ( - UserInCreate, - UserInLogin, - UserInResponse, - UserWithToken, -) -from app.resources import strings -from app.services import jwt -from app.services.authentication import check_email_is_taken, check_username_is_taken -from app.services.event import send_event - -router = APIRouter() - - -@router.post("/login", response_model=UserInResponse, name="auth:login") -async def login( - user_login: UserInLogin = Body(..., embed=True, alias="user"), - users_repo: UsersRepository = Depends(get_repository(UsersRepository)), - settings: AppSettings = Depends(get_app_settings), -) -> UserInResponse: - wrong_login_error = HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.INCORRECT_LOGIN_INPUT, - ) - - try: - user = await users_repo.get_user_by_email(email=user_login.email) - except EntityDoesNotExist as existence_error: - raise wrong_login_error from existence_error - - if not user.check_password(user_login.password): - raise wrong_login_error - - token = jwt.create_access_token_for_user( - user, - str(settings.secret_key.get_secret_value()), - ) - return UserInResponse( - user=UserWithToken( - username=user.username, - email=user.email, - bio=user.bio, - image=user.image, - token=token, - ), - ) - - -@router.post( - "", - status_code=HTTP_201_CREATED, - response_model=UserInResponse, - name="auth:register", -) -async def register( - user_create: UserInCreate = Body(..., embed=True, alias="user"), - users_repo: UsersRepository = Depends(get_repository(UsersRepository)), - settings: AppSettings = Depends(get_app_settings), -) -> UserInResponse: - if await check_username_is_taken(users_repo, user_create.username): - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.USERNAME_TAKEN, - ) - - if await check_email_is_taken(users_repo, user_create.email): - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.EMAIL_TAKEN, - ) - - user = await users_repo.create_user(**user_create.dict()) - - token = jwt.create_access_token_for_user( - user, - str(settings.secret_key.get_secret_value()), - ) - - send_event('user_created', { 'username': user.username }) - - return UserInResponse( - user=UserWithToken( - username=user.username, - email=user.email, - bio=user.bio, - image=user.image, - token=token, - ), - ) diff --git a/.framework/python/backend/app/api/routes/comments.py b/.framework/python/backend/app/api/routes/comments.py deleted file mode 100644 index 5810e3a..0000000 --- a/.framework/python/backend/app/api/routes/comments.py +++ /dev/null @@ -1,67 +0,0 @@ -from typing import Optional - -from fastapi import APIRouter, Body, Depends, Response -from starlette import status - -from app.api.dependencies.items import get_item_by_slug_from_path -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.comments import get_comment_by_id_from_path -from app.api.dependencies.database import get_repository -from app.db.repositories.comments import CommentsRepository -from app.models.domain.items import Item -from app.models.domain.comments import Comment -from app.models.domain.users import User -from app.models.schemas.comments import ( - CommentInCreate, - CommentInResponse, - ListOfCommentsInResponse, -) - -router = APIRouter() - - -@router.get( - "", - response_model=ListOfCommentsInResponse, - name="comments:get-comments-for-item", -) -async def list_comments_for_item( - item: Item = Depends(get_item_by_slug_from_path), - user: Optional[User] = Depends(get_current_user_authorizer(required=False)), - comments_repo: CommentsRepository = Depends(get_repository(CommentsRepository)), -) -> ListOfCommentsInResponse: - comments = await comments_repo.get_comments_for_item(item=item, user=user) - return ListOfCommentsInResponse(comments=comments) - - -@router.post( - "", - status_code=status.HTTP_201_CREATED, - response_model=CommentInResponse, - name="comments:create-comment-for-item", -) -async def create_comment_for_item( - comment_create: CommentInCreate = Body(..., embed=True, alias="comment"), - item: Item = Depends(get_item_by_slug_from_path), - user: User = Depends(get_current_user_authorizer()), - comments_repo: CommentsRepository = Depends(get_repository(CommentsRepository)), -) -> CommentInResponse: - comment = await comments_repo.create_comment_for_item( - body=comment_create.body, - item=item, - user=user, - ) - return CommentInResponse(comment=comment) - - -@router.delete( - "/{comment_id}", - status_code=status.HTTP_204_NO_CONTENT, - name="comments:delete-comment-from-item", - response_class=Response, -) -async def delete_comment_from_item( - comment: Comment = Depends(get_comment_by_id_from_path), - comments_repo: CommentsRepository = Depends(get_repository(CommentsRepository)), -) -> None: - await comments_repo.delete_comment(comment=comment) diff --git a/.framework/python/backend/app/api/routes/home.py b/.framework/python/backend/app/api/routes/home.py deleted file mode 100644 index 5521b49..0000000 --- a/.framework/python/backend/app/api/routes/home.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import APIRouter - -router = APIRouter() - -@router.get("/", status_code=200) -async def home(): - return "Anythink backend is up." - -@router.get("/health", status_code=200) -async def health(): - return "OK" diff --git a/.framework/python/backend/app/api/routes/items/__init__.py b/.framework/python/backend/app/api/routes/items/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/api/routes/items/api.py b/.framework/python/backend/app/api/routes/items/api.py deleted file mode 100644 index 731c4e0..0000000 --- a/.framework/python/backend/app/api/routes/items/api.py +++ /dev/null @@ -1,8 +0,0 @@ -from fastapi import APIRouter - -from app.api.routes.items import items_common, items_resource - -router = APIRouter() - -router.include_router(items_common.router, prefix="/items") -router.include_router(items_resource.router, prefix="/items") diff --git a/.framework/python/backend/app/api/routes/items/items_common.py b/.framework/python/backend/app/api/routes/items/items_common.py deleted file mode 100644 index 64447b4..0000000 --- a/.framework/python/backend/app/api/routes/items/items_common.py +++ /dev/null @@ -1,104 +0,0 @@ -from fastapi import APIRouter, Depends, HTTPException, Query -from starlette import status - -from app.api.dependencies.items import get_item_by_slug_from_path -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.database import get_repository -from app.db.repositories.items import ItemsRepository -from app.models.domain.items import Item -from app.models.domain.users import User -from app.models.schemas.items import ( - DEFAULT_ITEMS_LIMIT, - DEFAULT_ITEMS_OFFSET, - ItemForResponse, - ItemInResponse, - ListOfItemsInResponse, -) -from app.resources import strings - -router = APIRouter() - - -@router.get( - "/feed", - response_model=ListOfItemsInResponse, - name="items:get-user-feed-items", -) -async def get_items_for_user_feed( - limit: int = Query(DEFAULT_ITEMS_LIMIT, ge=1), - offset: int = Query(DEFAULT_ITEMS_OFFSET, ge=0), - user: User = Depends(get_current_user_authorizer()), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> ListOfItemsInResponse: - items = await items_repo.get_items_for_user_feed( - user=user, - limit=limit, - offset=offset, - ) - items_for_response = [ - ItemForResponse(**item.dict()) for item in items - ] - return ListOfItemsInResponse( - items=items_for_response, - items_count=len(items), - ) - - -@router.post( - "/{slug}/favorite", - response_model=ItemInResponse, - name="items:mark-item-favorite", -) -async def mark_item_as_favorite( - item: Item = Depends(get_item_by_slug_from_path), - user: User = Depends(get_current_user_authorizer()), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> ItemInResponse: - if not item.favorited: - await items_repo.add_item_into_favorites(item=item, user=user) - - return ItemInResponse( - item=ItemForResponse.from_orm( - item.copy( - update={ - "favorited": True, - "favorites_count": item.favorites_count + 1, - }, - ), - ), - ) - - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=strings.ITEM_IS_ALREADY_FAVORITED, - ) - - -@router.delete( - "/{slug}/favorite", - response_model=ItemInResponse, - name="items:unmark-item-favorite", -) -async def remove_item_from_favorites( - item: Item = Depends(get_item_by_slug_from_path), - user: User = Depends(get_current_user_authorizer()), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> ItemInResponse: - if item.favorited: - await items_repo.remove_item_from_favorites(item=item, user=user) - - return ItemInResponse( - item=ItemForResponse.from_orm( - item.copy( - update={ - "favorited": False, - "favorites_count": item.favorites_count - 1, - }, - ), - ), - ) - - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=strings.ITEM_IS_NOT_FAVORITED, - ) diff --git a/.framework/python/backend/app/api/routes/items/items_resource.py b/.framework/python/backend/app/api/routes/items/items_resource.py deleted file mode 100644 index e396091..0000000 --- a/.framework/python/backend/app/api/routes/items/items_resource.py +++ /dev/null @@ -1,122 +0,0 @@ -from typing import Optional - -from fastapi import APIRouter, Body, Depends, HTTPException, Response -from starlette import status - -from app.api.dependencies.items import ( - check_item_modification_permissions, - get_item_by_slug_from_path, - get_items_filters, -) -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.database import get_repository -from app.db.repositories.items import ItemsRepository -from app.models.domain.items import Item -from app.models.domain.users import User -from app.models.schemas.items import ( - ItemForResponse, - ItemInCreate, - ItemInResponse, - ItemInUpdate, - ItemsFilters, - ListOfItemsInResponse, -) -from app.resources import strings -from app.services.items import check_item_exists, get_slug_for_item -from app.services.event import send_event - -router = APIRouter() - - -@router.get("", response_model=ListOfItemsInResponse, name="items:list-items") -async def list_items( - items_filters: ItemsFilters = Depends(get_items_filters), - user: Optional[User] = Depends(get_current_user_authorizer(required=False)), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> ListOfItemsInResponse: - items = await items_repo.filter_items( - tag=items_filters.tag, - seller=items_filters.seller, - favorited=items_filters.favorited, - limit=items_filters.limit, - offset=items_filters.offset, - requested_user=user, - ) - items_for_response = [ - ItemForResponse.from_orm(item) for item in items - ] - return ListOfItemsInResponse( - items=items_for_response, - items_count=len(items), - ) - - -@router.post( - "", - status_code=status.HTTP_201_CREATED, - response_model=ItemInResponse, - name="items:create-item", -) -async def create_new_item( - item_create: ItemInCreate = Body(..., embed=True, alias="item"), - user: User = Depends(get_current_user_authorizer()), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> ItemInResponse: - slug = get_slug_for_item(item_create.title) - if await check_item_exists(items_repo, slug): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=strings.ITEM_ALREADY_EXISTS, - ) - item = await items_repo.create_item( - slug=slug, - title=item_create.title, - description=item_create.description, - body=item_create.body, - seller=user, - tags=item_create.tags, - image=item_create.image - ) - send_event('item_created', {'item': item_create.title}) - return ItemInResponse(item=ItemForResponse.from_orm(item)) - - -@router.get("/{slug}", response_model=ItemInResponse, name="items:get-item") -async def retrieve_item_by_slug( - item: Item = Depends(get_item_by_slug_from_path), -) -> ItemInResponse: - return ItemInResponse(item=ItemForResponse.from_orm(item)) - - -@router.put( - "/{slug}", - response_model=ItemInResponse, - name="items:update-item", - dependencies=[Depends(check_item_modification_permissions)], -) -async def update_item_by_slug( - item_update: ItemInUpdate = Body(..., embed=True, alias="item"), - current_item: Item = Depends(get_item_by_slug_from_path), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> ItemInResponse: - slug = get_slug_for_item(item_update.title) if item_update.title else None - item = await items_repo.update_item( - item=current_item, - slug=slug, - **item_update.dict(), - ) - return ItemInResponse(item=ItemForResponse.from_orm(item)) - - -@router.delete( - "/{slug}", - status_code=status.HTTP_204_NO_CONTENT, - name="items:delete-item", - dependencies=[Depends(check_item_modification_permissions)], - response_class=Response, -) -async def delete_item_by_slug( - item: Item = Depends(get_item_by_slug_from_path), - items_repo: ItemsRepository = Depends(get_repository(ItemsRepository)), -) -> None: - await items_repo.delete_item(item=item) diff --git a/.framework/python/backend/app/api/routes/ping.py b/.framework/python/backend/app/api/routes/ping.py deleted file mode 100644 index 3d0f5f0..0000000 --- a/.framework/python/backend/app/api/routes/ping.py +++ /dev/null @@ -1,17 +0,0 @@ -import json -import logging - -from fastapi import APIRouter, Depends, HTTPException -from app.services.event import send_event - -router = APIRouter() - -@router.get("") -async def check_ping(): - try: - res = send_event('ping', {}) - return res.json() - - except Exception as e: - logging.error(e) - raise HTTPException(status_code=500, detail="Error") diff --git a/.framework/python/backend/app/api/routes/profiles.py b/.framework/python/backend/app/api/routes/profiles.py deleted file mode 100644 index 6ec1bf0..0000000 --- a/.framework/python/backend/app/api/routes/profiles.py +++ /dev/null @@ -1,84 +0,0 @@ -from fastapi import APIRouter, Depends, HTTPException -from starlette.status import HTTP_400_BAD_REQUEST - -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.database import get_repository -from app.api.dependencies.profiles import get_profile_by_username_from_path -from app.db.repositories.profiles import ProfilesRepository -from app.models.domain.profiles import Profile -from app.models.domain.users import User -from app.models.schemas.profiles import ProfileInResponse -from app.resources import strings - -router = APIRouter() - - -@router.get( - "/{username}", - response_model=ProfileInResponse, - name="profiles:get-profile", -) -async def retrieve_profile_by_username( - profile: Profile = Depends(get_profile_by_username_from_path), -) -> ProfileInResponse: - return ProfileInResponse(profile=profile) - - -@router.post( - "/{username}/follow", - response_model=ProfileInResponse, - name="profiles:follow-user", -) -async def follow_for_user( - profile: Profile = Depends(get_profile_by_username_from_path), - user: User = Depends(get_current_user_authorizer()), - profiles_repo: ProfilesRepository = Depends(get_repository(ProfilesRepository)), -) -> ProfileInResponse: - if user.username == profile.username: - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.UNABLE_TO_FOLLOW_YOURSELF, - ) - - if profile.following: - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.USER_IS_ALREADY_FOLLOWED, - ) - - await profiles_repo.add_user_into_followers( - target_user=profile, - requested_user=user, - ) - - return ProfileInResponse(profile=profile.copy(update={"following": True})) - - -@router.delete( - "/{username}/follow", - response_model=ProfileInResponse, - name="profiles:unsubscribe-from-user", -) -async def unsubscribe_from_user( - profile: Profile = Depends(get_profile_by_username_from_path), - user: User = Depends(get_current_user_authorizer()), - profiles_repo: ProfilesRepository = Depends(get_repository(ProfilesRepository)), -) -> ProfileInResponse: - if user.username == profile.username: - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.UNABLE_TO_UNSUBSCRIBE_FROM_YOURSELF, - ) - - if not profile.following: - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.USER_IS_NOT_FOLLOWED, - ) - - await profiles_repo.remove_user_from_followers( - target_user=profile, - requested_user=user, - ) - - return ProfileInResponse(profile=profile.copy(update={"following": False})) diff --git a/.framework/python/backend/app/api/routes/tags.py b/.framework/python/backend/app/api/routes/tags.py deleted file mode 100644 index 4706187..0000000 --- a/.framework/python/backend/app/api/routes/tags.py +++ /dev/null @@ -1,15 +0,0 @@ -from fastapi import APIRouter, Depends - -from app.api.dependencies.database import get_repository -from app.db.repositories.tags import TagsRepository -from app.models.schemas.tags import TagsInList - -router = APIRouter() - - -@router.get("", response_model=TagsInList, name="tags:get-all") -async def get_all_tags( - tags_repo: TagsRepository = Depends(get_repository(TagsRepository)), -) -> TagsInList: - tags = await tags_repo.get_all_tags() - return TagsInList(tags=tags) diff --git a/.framework/python/backend/app/api/routes/users.py b/.framework/python/backend/app/api/routes/users.py deleted file mode 100644 index 81bcf97..0000000 --- a/.framework/python/backend/app/api/routes/users.py +++ /dev/null @@ -1,73 +0,0 @@ -from fastapi import APIRouter, Body, Depends, HTTPException -from starlette.status import HTTP_400_BAD_REQUEST - -from app.api.dependencies.authentication import get_current_user_authorizer -from app.api.dependencies.database import get_repository -from app.core.config import get_app_settings -from app.core.settings.app import AppSettings -from app.db.repositories.users import UsersRepository -from app.models.domain.users import User -from app.models.schemas.users import UserInResponse, UserInUpdate, UserWithToken -from app.resources import strings -from app.services import jwt -from app.services.authentication import check_email_is_taken, check_username_is_taken - -router = APIRouter() - - -@router.get("", response_model=UserInResponse, name="users:get-current-user") -async def retrieve_current_user( - user: User = Depends(get_current_user_authorizer()), - settings: AppSettings = Depends(get_app_settings), -) -> UserInResponse: - token = jwt.create_access_token_for_user( - user, - str(settings.secret_key.get_secret_value()), - ) - return UserInResponse( - user=UserWithToken( - username=user.username, - email=user.email, - bio=user.bio, - image=user.image, - token=token, - ), - ) - - -@router.put("", response_model=UserInResponse, name="users:update-current-user") -async def update_current_user( - user_update: UserInUpdate = Body(..., embed=True, alias="user"), - current_user: User = Depends(get_current_user_authorizer()), - users_repo: UsersRepository = Depends(get_repository(UsersRepository)), - settings: AppSettings = Depends(get_app_settings), -) -> UserInResponse: - if user_update.username and user_update.username != current_user.username: - if await check_username_is_taken(users_repo, user_update.username): - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.USERNAME_TAKEN, - ) - - if user_update.email and user_update.email != current_user.email: - if await check_email_is_taken(users_repo, user_update.email): - raise HTTPException( - status_code=HTTP_400_BAD_REQUEST, - detail=strings.EMAIL_TAKEN, - ) - - user = await users_repo.update_user(user=current_user, **user_update.dict()) - - token = jwt.create_access_token_for_user( - user, - str(settings.secret_key.get_secret_value()), - ) - return UserInResponse( - user=UserWithToken( - username=user.username, - email=user.email, - bio=user.bio, - image=user.image, - token=token, - ), - ) diff --git a/.framework/python/backend/app/core/__init__.py b/.framework/python/backend/app/core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/core/config.py b/.framework/python/backend/app/core/config.py deleted file mode 100644 index 87f58a8..0000000 --- a/.framework/python/backend/app/core/config.py +++ /dev/null @@ -1,21 +0,0 @@ -from functools import lru_cache -from typing import Dict, Type - -from app.core.settings.app import AppSettings -from app.core.settings.base import AppEnvTypes, BaseAppSettings -from app.core.settings.development import DevAppSettings -from app.core.settings.production import ProdAppSettings -from app.core.settings.test import TestAppSettings - -environments: Dict[AppEnvTypes, Type[AppSettings]] = { - AppEnvTypes.dev: DevAppSettings, - AppEnvTypes.prod: ProdAppSettings, - AppEnvTypes.test: TestAppSettings, -} - - -@lru_cache -def get_app_settings() -> AppSettings: - app_env = BaseAppSettings().app_env - config = environments[app_env] - return config() diff --git a/.framework/python/backend/app/core/events.py b/.framework/python/backend/app/core/events.py deleted file mode 100644 index 3e82ee3..0000000 --- a/.framework/python/backend/app/core/events.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Callable - -from fastapi import FastAPI -from loguru import logger - -from app.core.settings.app import AppSettings -from app.db.events import close_db_connection, connect_to_db - - -def create_start_app_handler( - app: FastAPI, - settings: AppSettings, -) -> Callable: # type: ignore - async def start_app() -> None: - await connect_to_db(app, settings) - - return start_app - - -def create_stop_app_handler(app: FastAPI) -> Callable: # type: ignore - @logger.catch - async def stop_app() -> None: - await close_db_connection(app) - - return stop_app diff --git a/.framework/python/backend/app/core/logging.py b/.framework/python/backend/app/core/logging.py deleted file mode 100644 index 10ceda7..0000000 --- a/.framework/python/backend/app/core/logging.py +++ /dev/null @@ -1,25 +0,0 @@ -import logging -from types import FrameType -from typing import cast - -from loguru import logger - - -class InterceptHandler(logging.Handler): - def emit(self, record: logging.LogRecord) -> None: # pragma: no cover - # Get corresponding Loguru level if it exists - try: - level = logger.level(record.levelname).name - except ValueError: - level = str(record.levelno) - - # Find caller from where originated the logged message - frame, depth = logging.currentframe(), 2 - while frame.f_code.co_filename == logging.__file__: # noqa: WPS609 - frame = cast(FrameType, frame.f_back) - depth += 1 - - logger.opt(depth=depth, exception=record.exc_info).log( - level, - record.getMessage(), - ) diff --git a/.framework/python/backend/app/core/settings/__init__.py b/.framework/python/backend/app/core/settings/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/core/settings/app.py b/.framework/python/backend/app/core/settings/app.py deleted file mode 100644 index fc0c606..0000000 --- a/.framework/python/backend/app/core/settings/app.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging -import sys -from typing import Any, Dict, List, Tuple - -from loguru import logger -from pydantic import PostgresDsn, SecretStr - -from app.core.logging import InterceptHandler -from app.core.settings.base import BaseAppSettings - - -class AppSettings(BaseAppSettings): - debug: bool = False - docs_url: str = "/docs" - openapi_prefix: str = "" - openapi_url: str = "/openapi.json" - redoc_url: str = "/redoc" - title: str = "FastAPI example application" - version: str = "0.0.0" - - database_url: PostgresDsn - max_connection_count: int = 5 - min_connection_count: int = 5 - - secret_key: SecretStr = SecretStr("secret") - - api_prefix: str = "/api" - - jwt_token_prefix: str = "Token" - - allowed_hosts: List[str] = ["*"] - - logging_level: int = logging.INFO - loggers: Tuple[str, str] = ("uvicorn.asgi", "uvicorn.access") - - class Config: - validate_assignment = True - - @property - def fastapi_kwargs(self) -> Dict[str, Any]: - return { - "debug": self.debug, - "docs_url": self.docs_url, - "openapi_prefix": self.openapi_prefix, - "openapi_url": self.openapi_url, - "redoc_url": self.redoc_url, - "title": self.title, - "version": self.version, - } - - def configure_logging(self) -> None: - logging.getLogger().handlers = [InterceptHandler()] - for logger_name in self.loggers: - logging_logger = logging.getLogger(logger_name) - logging_logger.handlers = [InterceptHandler(level=self.logging_level)] - - logger.configure(handlers=[{"sink": sys.stderr, "level": self.logging_level}]) diff --git a/.framework/python/backend/app/core/settings/base.py b/.framework/python/backend/app/core/settings/base.py deleted file mode 100644 index 0397cbb..0000000 --- a/.framework/python/backend/app/core/settings/base.py +++ /dev/null @@ -1,16 +0,0 @@ -from enum import Enum - -from pydantic import BaseSettings - - -class AppEnvTypes(Enum): - prod: str = "prod" - dev: str = "dev" - test: str = "test" - - -class BaseAppSettings(BaseSettings): - app_env: AppEnvTypes = AppEnvTypes.prod - - class Config: - env_file = ".env" diff --git a/.framework/python/backend/app/core/settings/development.py b/.framework/python/backend/app/core/settings/development.py deleted file mode 100644 index 041a77d..0000000 --- a/.framework/python/backend/app/core/settings/development.py +++ /dev/null @@ -1,14 +0,0 @@ -import logging - -from app.core.settings.app import AppSettings - - -class DevAppSettings(AppSettings): - debug: bool = True - - title: str = "Dev FastAPI example application" - - logging_level: int = logging.DEBUG - - class Config(AppSettings.Config): - env_file = ".env" diff --git a/.framework/python/backend/app/core/settings/production.py b/.framework/python/backend/app/core/settings/production.py deleted file mode 100644 index f2d3eab..0000000 --- a/.framework/python/backend/app/core/settings/production.py +++ /dev/null @@ -1,6 +0,0 @@ -from app.core.settings.app import AppSettings - - -class ProdAppSettings(AppSettings): - class Config(AppSettings.Config): - env_file = "prod.env" diff --git a/.framework/python/backend/app/core/settings/test.py b/.framework/python/backend/app/core/settings/test.py deleted file mode 100644 index bea3c53..0000000 --- a/.framework/python/backend/app/core/settings/test.py +++ /dev/null @@ -1,19 +0,0 @@ -import logging - -from pydantic import PostgresDsn, SecretStr - -from app.core.settings.app import AppSettings - - -class TestAppSettings(AppSettings): - debug: bool = True - - title: str = "Test FastAPI example application" - - secret_key: SecretStr = SecretStr("test_secret") - - database_url: PostgresDsn - max_connection_count: int = 5 - min_connection_count: int = 5 - - logging_level: int = logging.DEBUG diff --git a/.framework/python/backend/app/db/__init__.py b/.framework/python/backend/app/db/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/db/errors.py b/.framework/python/backend/app/db/errors.py deleted file mode 100644 index bb3ef66..0000000 --- a/.framework/python/backend/app/db/errors.py +++ /dev/null @@ -1,2 +0,0 @@ -class EntityDoesNotExist(Exception): - """Raised when entity was not found in database.""" diff --git a/.framework/python/backend/app/db/events.py b/.framework/python/backend/app/db/events.py deleted file mode 100644 index 5c42303..0000000 --- a/.framework/python/backend/app/db/events.py +++ /dev/null @@ -1,29 +0,0 @@ -import asyncpg -from fastapi import FastAPI -from loguru import logger - -from app.core.settings.app import AppSettings - - -async def connect_to_db(app: FastAPI, settings: AppSettings) -> None: - logger.info("Connecting to PostgreSQL") - - # SQLAlchemy >= 1.4 deprecated the use of `postgres://` in favor of `postgresql://` - # for the database connection url - database_url = settings.database_url.replace("postgres://", "postgresql://") - - app.state.pool = await asyncpg.create_pool( - str(database_url), - min_size=settings.min_connection_count, - max_size=settings.max_connection_count, - ) - - logger.info("Connection established") - - -async def close_db_connection(app: FastAPI) -> None: - logger.info("Closing connection to database") - - await app.state.pool.close() - - logger.info("Connection closed") diff --git a/.framework/python/backend/app/db/migrations/env.py b/.framework/python/backend/app/db/migrations/env.py deleted file mode 100644 index 93122b2..0000000 --- a/.framework/python/backend/app/db/migrations/env.py +++ /dev/null @@ -1,41 +0,0 @@ -import pathlib -import sys -from logging.config import fileConfig - -from alembic import context -from sqlalchemy import engine_from_config, pool - -sys.path.append(str(pathlib.Path(__file__).resolve().parents[3])) - -from app.core.config import get_app_settings # isort:skip - -SETTINGS = get_app_settings() - -# SQLAlchemy >= 1.4 deprecated the use of `postgres://` in favor of `postgresql://` -# for the database connection url -DATABASE_URL = SETTINGS.database_url.replace("postgres://", "postgresql://") - -config = context.config - -fileConfig(config.config_file_name) # type: ignore - -target_metadata = None - -config.set_main_option("sqlalchemy.url", str(DATABASE_URL)) - - -def run_migrations_online() -> None: - connectable = engine_from_config( - config.get_section(config.config_ini_section), - prefix="sqlalchemy.", - poolclass=pool.NullPool, - ) - - with connectable.connect() as connection: - context.configure(connection=connection, target_metadata=target_metadata) - - with context.begin_transaction(): - context.run_migrations() - - -run_migrations_online() diff --git a/.framework/python/backend/app/db/migrations/script.py.mako b/.framework/python/backend/app/db/migrations/script.py.mako deleted file mode 100644 index 3217cf0..0000000 --- a/.framework/python/backend/app/db/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade() -> None: - ${upgrades if upgrades else "pass"} - - -def downgrade() -> None: - ${downgrades if downgrades else "pass"} diff --git a/.framework/python/backend/app/db/migrations/versions/fdf8821871d7_main_tables.py b/.framework/python/backend/app/db/migrations/versions/fdf8821871d7_main_tables.py deleted file mode 100644 index 04f1036..0000000 --- a/.framework/python/backend/app/db/migrations/versions/fdf8821871d7_main_tables.py +++ /dev/null @@ -1,217 +0,0 @@ -"""main tables - -Revision ID: fdf8821871d7 -Revises: -Create Date: 2019-09-22 01:36:44.791880 - -""" -from typing import Tuple - -import sqlalchemy as sa -from alembic import op -from sqlalchemy import func - -revision = "fdf8821871d7" -down_revision = None -branch_labels = None -depends_on = None - - -def create_updated_at_trigger() -> None: - op.execute( - """ - CREATE FUNCTION update_updated_at_column() - RETURNS TRIGGER AS - $$ - BEGIN - NEW.updated_at = now(); - RETURN NEW; - END; - $$ language 'plpgsql'; - """ - ) - - -def timestamps() -> Tuple[sa.Column, sa.Column]: - return ( - sa.Column( - "created_at", - sa.TIMESTAMP(timezone=True), - nullable=False, - server_default=func.now(), - ), - sa.Column( - "updated_at", - sa.TIMESTAMP(timezone=True), - nullable=False, - server_default=func.now(), - onupdate=func.current_timestamp(), - ), - ) - - -def create_users_table() -> None: - op.create_table( - "users", - sa.Column("id", sa.Integer, primary_key=True), - sa.Column("username", sa.Text, unique=True, nullable=False, index=True), - sa.Column("email", sa.Text, unique=True, nullable=False, index=True), - sa.Column("salt", sa.Text, nullable=False), - sa.Column("hashed_password", sa.Text), - sa.Column("bio", sa.Text, nullable=False, server_default=""), - sa.Column("image", sa.Text), - *timestamps(), - ) - op.execute( - """ - CREATE TRIGGER update_user_modtime - BEFORE UPDATE - ON users - FOR EACH ROW - EXECUTE PROCEDURE update_updated_at_column(); - """ - ) - - -def create_followers_to_followings_table() -> None: - op.create_table( - "followers_to_followings", - sa.Column( - "follower_id", - sa.Integer, - sa.ForeignKey("users.id", ondelete="CASCADE"), - nullable=False, - ), - sa.Column( - "following_id", - sa.Integer, - sa.ForeignKey("users.id", ondelete="CASCADE"), - nullable=False, - ), - ) - op.create_primary_key( - "pk_followers_to_followings", - "followers_to_followings", - ["follower_id", "following_id"], - ) - - -def create_items_table() -> None: - op.create_table( - "items", - sa.Column("id", sa.Integer, primary_key=True), - sa.Column("slug", sa.Text, unique=True, nullable=False, index=True), - sa.Column("title", sa.Text, nullable=False), - sa.Column("description", sa.Text, nullable=False), - sa.Column("body", sa.Text, nullable=True), - sa.Column("image", sa.Text, nullable=True), - sa.Column( - "seller_id", sa.Integer, sa.ForeignKey("users.id", ondelete="SET NULL") - ), - *timestamps(), - ) - op.execute( - """ - CREATE TRIGGER update_item_modtime - BEFORE UPDATE - ON items - FOR EACH ROW - EXECUTE PROCEDURE update_updated_at_column(); - """ - ) - - -def create_tags_table() -> None: - op.create_table("tags", sa.Column("tag", sa.Text, primary_key=True)) - - -def create_items_to_tags_table() -> None: - op.create_table( - "items_to_tags", - sa.Column( - "item_id", - sa.Integer, - sa.ForeignKey("items.id", ondelete="CASCADE"), - nullable=False, - ), - sa.Column( - "tag", - sa.Text, - sa.ForeignKey("tags.tag", ondelete="CASCADE"), - nullable=False, - ), - ) - op.create_primary_key( - "pk_items_to_tags", "items_to_tags", ["item_id", "tag"] - ) - - -def create_favorites_table() -> None: - op.create_table( - "favorites", - sa.Column( - "user_id", - sa.Integer, - sa.ForeignKey("users.id", ondelete="CASCADE"), - nullable=False, - ), - sa.Column( - "item_id", - sa.Integer, - sa.ForeignKey("items.id", ondelete="CASCADE"), - nullable=False, - ), - ) - op.create_primary_key("pk_favorites", "favorites", ["user_id", "item_id"]) - - -def create_comments_table() -> None: - op.create_table( - "comments", - sa.Column("id", sa.Integer, primary_key=True), - sa.Column("body", sa.Text, nullable=False), - sa.Column( - "seller_id", - sa.Integer, - sa.ForeignKey("users.id", ondelete="CASCADE"), - nullable=False, - ), - sa.Column( - "item_id", - sa.Integer, - sa.ForeignKey("items.id", ondelete="CASCADE"), - nullable=False, - ), - *timestamps(), - ) - op.execute( - """ - CREATE TRIGGER update_comment_modtime - BEFORE UPDATE - ON comments - FOR EACH ROW - EXECUTE PROCEDURE update_updated_at_column(); - """ - ) - - -def upgrade() -> None: - create_updated_at_trigger() - create_users_table() - create_followers_to_followings_table() - create_items_table() - create_tags_table() - create_items_to_tags_table() - create_favorites_table() - create_comments_table() - - -def downgrade() -> None: - op.drop_table("comments") - op.drop_table("favorites") - op.drop_table("items_to_tags") - op.drop_table("tags") - op.drop_table("items") - op.drop_table("followers_to_followings") - op.drop_table("users") - op.execute("DROP FUNCTION update_updated_at_column") diff --git a/.framework/python/backend/app/db/queries/__init__.py b/.framework/python/backend/app/db/queries/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/db/queries/queries.py b/.framework/python/backend/app/db/queries/queries.py deleted file mode 100644 index a190595..0000000 --- a/.framework/python/backend/app/db/queries/queries.py +++ /dev/null @@ -1,5 +0,0 @@ -import pathlib - -import aiosql - -queries = aiosql.from_path(pathlib.Path(__file__).parent / "sql", "asyncpg") diff --git a/.framework/python/backend/app/db/queries/queries.pyi b/.framework/python/backend/app/db/queries/queries.pyi deleted file mode 100644 index 5f20e85..0000000 --- a/.framework/python/backend/app/db/queries/queries.pyi +++ /dev/null @@ -1,125 +0,0 @@ -"""Typings for queries generated by aiosql""" - -from typing import Dict, Optional, Sequence - -from asyncpg import Connection, Record - -class TagsQueriesMixin: - async def get_all_tags(self, conn: Connection) -> Record: ... - async def create_new_tags( - self, conn: Connection, tags: Sequence[Dict[str, str]] - ) -> None: ... - -class UsersQueriesMixin: - async def get_user_by_email(self, conn: Connection, *, email: str) -> Record: ... - async def get_user_by_username( - self, conn: Connection, *, username: str - ) -> Record: ... - async def create_new_user( - self, - conn: Connection, - *, - username: str, - email: str, - salt: str, - hashed_password: str - ) -> Record: ... - async def update_user_by_username( - self, - conn: Connection, - *, - username: str, - new_username: str, - new_email: str, - new_salt: str, - new_password: str, - new_bio: Optional[str], - new_image: Optional[str] - ) -> Record: ... - -class ProfilesQueriesMixin: - async def is_user_following_for_another( - self, conn: Connection, *, follower_username: str, following_username: str - ) -> Record: ... - async def subscribe_user_to_another( - self, conn: Connection, *, follower_username: str, following_username: str - ) -> None: ... - async def unsubscribe_user_from_another( - self, conn: Connection, *, follower_username: str, following_username: str - ) -> None: ... - -class CommentsQueriesMixin: - async def get_comments_for_item_by_slug( - self, conn: Connection, *, slug: str - ) -> Record: ... - async def get_comment_by_id_and_slug( - self, conn: Connection, *, comment_id: int, item_slug: str - ) -> Record: ... - async def create_new_comment( - self, conn: Connection, *, body: str, item_slug: str, seller_username: str - ) -> Record: ... - async def delete_comment_by_id( - self, conn: Connection, *, comment_id: int, seller_username: str - ) -> None: ... - -class ItemsQueriesMixin: - async def add_item_to_favorites( - self, conn: Connection, *, username: str, slug: str - ) -> None: ... - async def remove_item_from_favorites( - self, conn: Connection, *, username: str, slug: str - ) -> None: ... - async def is_item_in_favorites( - self, conn: Connection, *, username: str, slug: str - ) -> Record: ... - async def get_favorites_count_for_item( - self, conn: Connection, *, slug: str - ) -> Record: ... - async def get_tags_for_item_by_slug( - self, conn: Connection, *, slug: str - ) -> Record: ... - async def get_item_by_slug(self, conn: Connection, *, slug: str) -> Record: ... - async def create_new_item( - self, - conn: Connection, - *, - slug: str, - title: str, - description: str, - body: str, - seller_username: str, - image: str - ) -> Record: ... - async def add_tags_to_item( - self, conn: Connection, tags_slugs: Sequence[Dict[str, str]] - ) -> None: ... - async def delete_tags_from_item( - self, conn: Connection, *, slug: str - ) -> None: ... - async def update_item( - self, - conn: Connection, - *, - slug: str, - seller_username: str, - new_title: str, - new_body: str, - new_description: str, - new_image: str - ) -> Record: ... - async def delete_item( - self, conn: Connection, *, slug: str, seller_username: str - ) -> None: ... - async def get_items_for_feed( - self, conn: Connection, *, follower_username: str, limit: int, offset: int - ) -> Record: ... - -class Queries( - TagsQueriesMixin, - UsersQueriesMixin, - ProfilesQueriesMixin, - CommentsQueriesMixin, - ItemsQueriesMixin, -): ... - -queries: Queries diff --git a/.framework/python/backend/app/db/queries/sql/comments.sql b/.framework/python/backend/app/db/queries/sql/comments.sql deleted file mode 100644 index 7a342ec..0000000 --- a/.framework/python/backend/app/db/queries/sql/comments.sql +++ /dev/null @@ -1,41 +0,0 @@ --- name: get-comments-for-item-by-slug -SELECT c.id, - c.body, - c.created_at, - c.updated_at, - (SELECT username FROM users WHERE id = c.seller_id) as seller_username -FROM comments c - INNER JOIN items a ON c.item_id = a.id AND (a.slug = :slug) -ORDER BY c.created_at DESC; - --- name: get-comment-by-id-and-slug^ -SELECT c.id, - c.body, - c.created_at, - c.updated_at, - (SELECT username FROM users WHERE id = c.seller_id) as seller_username -FROM comments c - INNER JOIN items a ON c.item_id = a.id AND (a.slug = :item_slug) -WHERE c.id = :comment_id; - --- name: create-new-comment 0 THEN TRUE ELSE FALSE END AS favorited -FROM favorites -WHERE user_id = (SELECT id FROM users WHERE username = :username) - AND item_id = (SELECT id FROM items WHERE slug = :slug); - - --- name: get-favorites-count-for-item^ -SELECT count(*) as favorites_count -FROM favorites -WHERE item_id = (SELECT id FROM items WHERE slug = :slug); - - --- name: get-tags-for-item-by-slug -SELECT t.tag -FROM tags t - INNER JOIN items_to_tags att ON - t.tag = att.tag - AND - att.item_id = (SELECT id FROM items WHERE slug = :slug); - - --- name: get-item-by-slug^ -SELECT id, - slug, - title, - description, - body, - image, - created_at, - updated_at, - (SELECT username FROM users WHERE id = seller_id) AS seller_username -FROM items -WHERE slug = :slug -LIMIT 1; - - --- name: create-new-item None: - super().__init__("${0}".format(count)) - - -class TypedTable(Table): - __table__ = "" - - def __init__( - self, - name: Optional[str] = None, - schema: Optional[str] = None, - alias: Optional[str] = None, - query_cls: Optional[Query] = None, - ) -> None: - if name is None: - if self.__table__: - name = self.__table__ - else: - name = self.__class__.__name__ - - super().__init__(name, schema, alias, query_cls) - - -class Users(TypedTable): - __table__ = "users" - - id: int - username: str - - -class Items(TypedTable): - __table__ = "items" - - id: int - slug: str - title: str - description: str - body: str - seller_id: int - created_at: datetime - updated_at: datetime - - -class Tags(TypedTable): - __table__ = "tags" - - tag: str - - -class ItemsToTags(TypedTable): - __table__ = "items_to_tags" - - item_id: int - tag: str - - -class Favorites(TypedTable): - __table__ = "favorites" - - item_id: int - user_id: int - - -users = Users() -items = Items() -tags = Tags() -items_to_tags = ItemsToTags() -favorites = Favorites() diff --git a/.framework/python/backend/app/db/repositories/__init__.py b/.framework/python/backend/app/db/repositories/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/db/repositories/base.py b/.framework/python/backend/app/db/repositories/base.py deleted file mode 100644 index 8f8a5c3..0000000 --- a/.framework/python/backend/app/db/repositories/base.py +++ /dev/null @@ -1,10 +0,0 @@ -from asyncpg.connection import Connection - - -class BaseRepository: - def __init__(self, conn: Connection) -> None: - self._conn = conn - - @property - def connection(self) -> Connection: - return self._conn diff --git a/.framework/python/backend/app/db/repositories/comments.py b/.framework/python/backend/app/db/repositories/comments.py deleted file mode 100644 index cb432b3..0000000 --- a/.framework/python/backend/app/db/repositories/comments.py +++ /dev/null @@ -1,103 +0,0 @@ -from typing import List, Optional - -from asyncpg import Connection, Record - -from app.db.errors import EntityDoesNotExist -from app.db.queries.queries import queries -from app.db.repositories.base import BaseRepository -from app.db.repositories.profiles import ProfilesRepository -from app.models.domain.items import Item -from app.models.domain.comments import Comment -from app.models.domain.users import User - - -class CommentsRepository(BaseRepository): - def __init__(self, conn: Connection) -> None: - super().__init__(conn) - self._profiles_repo = ProfilesRepository(conn) - - async def get_comment_by_id( - self, - *, - comment_id: int, - item: Item, - user: Optional[User] = None, - ) -> Comment: - comment_row = await queries.get_comment_by_id_and_slug( - self.connection, - comment_id=comment_id, - item_slug=item.slug, - ) - if comment_row: - return await self._get_comment_from_db_record( - comment_row=comment_row, - seller_username=comment_row["seller_username"], - requested_user=user, - ) - - raise EntityDoesNotExist( - "comment with id {0} does not exist".format(comment_id), - ) - - async def get_comments_for_item( - self, - *, - item: Item, - user: Optional[User] = None, - ) -> List[Comment]: - comments_rows = await queries.get_comments_for_item_by_slug( - self.connection, - slug=item.slug, - ) - return [ - await self._get_comment_from_db_record( - comment_row=comment_row, - seller_username=comment_row["seller_username"], - requested_user=user, - ) - for comment_row in comments_rows - ] - - async def create_comment_for_item( - self, - *, - body: str, - item: Item, - user: User, - ) -> Comment: - comment_row = await queries.create_new_comment( - self.connection, - body=body, - item_slug=item.slug, - seller_username=user.username, - ) - return await self._get_comment_from_db_record( - comment_row=comment_row, - seller_username=comment_row["seller_username"], - requested_user=user, - ) - - async def delete_comment(self, *, comment: Comment) -> None: - await queries.delete_comment_by_id( - self.connection, - comment_id=comment.id_, - seller_username=comment.seller.username, - ) - - async def _get_comment_from_db_record( - self, - *, - comment_row: Record, - seller_username: str, - requested_user: Optional[User], - ) -> Comment: - return Comment( - id_=comment_row["id"], - body=comment_row["body"], - seller=await self._profiles_repo.get_profile_by_username( - username=seller_username, - requested_user=requested_user, - ), - created_at=comment_row["created_at"], - updated_at=comment_row["updated_at"], - ) diff --git a/.framework/python/backend/app/db/repositories/items.py b/.framework/python/backend/app/db/repositories/items.py deleted file mode 100644 index 8ff146a..0000000 --- a/.framework/python/backend/app/db/repositories/items.py +++ /dev/null @@ -1,353 +0,0 @@ -from typing import List, Optional, Sequence, Union - -from asyncpg import Connection, Record -from pypika import Query, Order - -from app.db.errors import EntityDoesNotExist -from app.db.queries.queries import queries -from app.db.queries.tables import ( - Parameter, - items, - items_to_tags, - favorites, - tags as tags_table, - users, -) -from app.db.repositories.base import BaseRepository -from app.db.repositories.profiles import ProfilesRepository -from app.db.repositories.tags import TagsRepository -from app.models.domain.items import Item -from app.models.domain.users import User - -SELLER_USERNAME_ALIAS = "seller_username" -SLUG_ALIAS = "slug" - -CAMEL_OR_SNAKE_CASE_TO_WORDS = r"^[a-z\d_\-]+|[A-Z\d_\-][^A-Z\d_\-]*" - - -class ItemsRepository(BaseRepository): # noqa: WPS214 - def __init__(self, conn: Connection) -> None: - super().__init__(conn) - self._profiles_repo = ProfilesRepository(conn) - self._tags_repo = TagsRepository(conn) - - async def create_item( # noqa: WPS211 - self, - *, - slug: str, - title: str, - description: str, - seller: User, - body: Optional[str] = None, - image: Optional[str] = None, - tags: Optional[Sequence[str]] = None, - ) -> Item: - async with self.connection.transaction(): - item_row = await queries.create_new_item( - self.connection, - slug=slug, - title=title, - description=description, - body=body, - seller_username=seller.username, - image=image - ) - - if tags: - await self._tags_repo.create_tags_that_dont_exist(tags=tags) - await self._link_item_with_tags(slug=slug, tags=tags) - - return await self._get_item_from_db_record( - item_row=item_row, - slug=slug, - seller_username=item_row[SELLER_USERNAME_ALIAS], - requested_user=seller, - ) - - async def update_item( # noqa: WPS211 - self, - *, - item: Item, - slug: Optional[str] = None, - title: Optional[str] = None, - body: Optional[str] = None, - description: Optional[str] = None, - image: Optional[str] = None, - tags: Optional[Sequence[str]] = None, - ) -> Item: - updated_item = item.copy(deep=True) - updated_item.title = title or item.title - updated_item.body = body or item.body - updated_item.description = description or item.description - updated_item.image = image or item.image - - async with self.connection.transaction(): - updated_item.updated_at = await queries.update_item( - self.connection, - slug=item.slug, - seller_username=item.seller.username, - new_title=updated_item.title, - new_body=updated_item.body, - new_description=updated_item.description, - new_image=updated_item.image, - ) - - if tags: - await self._tags_repo.create_tags_that_dont_exist(tags=tags) - await self._unlink_item_from_tags(slug=item.slug) - await self._link_item_with_tags(slug=item.slug, tags=tags) - - return await self.get_item_by_slug( - slug=item.slug, - requested_user=item.seller, - ) - - async def delete_item(self, *, item: Item) -> None: - async with self.connection.transaction(): - await queries.delete_item( - self.connection, - slug=item.slug, - seller_username=item.seller.username, - ) - - async def filter_items( # noqa: WPS211 - self, - *, - tag: Optional[str] = None, - seller: Optional[str] = None, - favorited: Optional[str] = None, - limit: int = 20, - offset: int = 0, - requested_user: Optional[User] = None, - ) -> List[Item]: - query_params: List[Union[str, int]] = [] - query_params_count = 0 - - # fmt: off - query = Query.from_( - items, - ).select( - items.id, - items.slug, - items.title, - items.description, - items.body, - items.image, - items.created_at, - items.updated_at, - Query.from_( - users, - ).where( - users.id == items.seller_id, - ).select( - users.username, - ).as_( - SELLER_USERNAME_ALIAS, - ), - ).orderby( - items.created_at, order=Order.desc, - ) - # fmt: on - - if tag: - query_params.append(tag) - query_params_count += 1 - - # fmt: off - query = query.join( - items_to_tags, - ).on( - (items.id == items_to_tags.item_id) & ( - items_to_tags.tag == Query.from_( - tags_table, - ).where( - tags_table.tag == Parameter(query_params_count), - ).select( - tags_table.tag, - ) - ), - ) - # fmt: on - - if seller: - query_params.append(seller) - query_params_count += 1 - - # fmt: off - query = query.join( - users, - ).on( - (items.seller_id == users.id) & ( - users.id == Query.from_( - users, - ).where( - users.username == Parameter(query_params_count), - ).select( - users.id, - ) - ), - ) - # fmt: on - - if favorited: - query_params.append(favorited) - query_params_count += 1 - - # fmt: off - query = query.join( - favorites, - ).on( - (items.id == favorites.item_id) & ( - favorites.user_id == Query.from_( - users, - ).where( - users.username == Parameter(query_params_count), - ).select( - users.id, - ) - ), - ) - # fmt: on - - query = query.limit(Parameter(query_params_count + 1)).offset( - Parameter(query_params_count + 2), - ) - query_params.extend([limit, offset]) - - items_rows = await self.connection.fetch(query.get_sql(), *query_params) - - return [ - await self.get_item_by_slug(slug=item_row['slug'], requested_user=requested_user) - for item_row in items_rows - ] - - async def get_items_for_user_feed( - self, - *, - user: User, - limit: int = 20, - offset: int = 0, - ) -> List[Item]: - items_rows = await queries.get_items_for_feed( - self.connection, - follower_username=user.username, - limit=limit, - offset=offset, - ) - return [ - await self._get_item_from_db_record( - item_row=item_row, - slug=item_row[SLUG_ALIAS], - seller_username=item_row[SELLER_USERNAME_ALIAS], - requested_user=user, - ) - for item_row in items_rows - ] - - async def get_item_by_slug( - self, - *, - slug: str, - requested_user: Optional[User] = None, - ) -> Item: - item_row = await queries.get_item_by_slug(self.connection, slug=slug) - if item_row: - return await self._get_item_from_db_record( - item_row=item_row, - slug=item_row[SLUG_ALIAS], - seller_username=item_row[SELLER_USERNAME_ALIAS], - requested_user=requested_user, - ) - - raise EntityDoesNotExist("item with slug {0} does not exist".format(slug)) - - async def get_tags_for_item_by_slug(self, *, slug: str) -> List[str]: - tag_rows = await queries.get_tags_for_item_by_slug( - self.connection, - slug=slug, - ) - return [row["tag"] for row in tag_rows] - - async def get_favorites_count_for_item_by_slug(self, *, slug: str) -> int: - return ( - await queries.get_favorites_count_for_item(self.connection, slug=slug) - )["favorites_count"] - - async def is_item_favorited_by_user(self, *, slug: str, user: User) -> bool: - return ( - await queries.is_item_in_favorites( - self.connection, - username=user.username, - slug=slug, - ) - )["favorited"] - - async def add_item_into_favorites(self, *, item: Item, user: User) -> None: - await queries.add_item_to_favorites( - self.connection, - username=user.username, - slug=item.slug, - ) - - async def remove_item_from_favorites( - self, - *, - item: Item, - user: User, - ) -> None: - await queries.remove_item_from_favorites( - self.connection, - username=user.username, - slug=item.slug, - ) - - async def _get_item_from_db_record( - self, - *, - item_row: Record, - slug: str, - seller_username: str, - requested_user: Optional[User], - ) -> Item: - title_query = Query.from_(items).select(items.title).where(items.slug == slug) - result_rows = await self.connection.fetch(title_query.get_sql()) - if not len(result_rows): - raise Exception(f'No item with slug {slug}') - title = result_rows[0]['title'] - - return Item( - id_=item_row["id"], - slug=slug, - title=title, - description=item_row["description"], - body=item_row["body"], - image=item_row["image"], - seller=await self._profiles_repo.get_profile_by_username( - username=seller_username, - requested_user=requested_user, - ), - tags=await self.get_tags_for_item_by_slug(slug=slug), - favorites_count=await self.get_favorites_count_for_item_by_slug( - slug=slug, - ), - favorited=await self.is_item_favorited_by_user( - slug=slug, - user=requested_user, - ) - if requested_user - else False, - created_at=item_row["created_at"], - updated_at=item_row["updated_at"], - ) - - async def _link_item_with_tags(self, *, slug: str, tags: Sequence[str]) -> None: - await queries.add_tags_to_item( - self.connection, - [{SLUG_ALIAS: slug, "tag": tag} for tag in tags], - ) - - async def _unlink_item_with_tags(self, *, slug: str) -> None: - await queries.delete_tags_from_item( - self.connection, - slug=slug, - ) diff --git a/.framework/python/backend/app/db/repositories/profiles.py b/.framework/python/backend/app/db/repositories/profiles.py deleted file mode 100644 index 20d43a0..0000000 --- a/.framework/python/backend/app/db/repositories/profiles.py +++ /dev/null @@ -1,74 +0,0 @@ -from typing import Optional, Union - -from asyncpg import Connection - -from app.db.queries.queries import queries -from app.db.repositories.base import BaseRepository -from app.db.repositories.users import UsersRepository -from app.models.domain.profiles import Profile -from app.models.domain.users import User - -UserLike = Union[User, Profile] - - -class ProfilesRepository(BaseRepository): - def __init__(self, conn: Connection): - super().__init__(conn) - self._users_repo = UsersRepository(conn) - - async def get_profile_by_username( - self, - *, - username: str, - requested_user: Optional[UserLike], - ) -> Profile: - user = await self._users_repo.get_user_by_username(username=username) - - profile = Profile(username=user.username, bio=user.bio, image=user.image) - if requested_user: - profile.following = await self.is_user_following_for_another_user( - target_user=user, - requested_user=requested_user, - ) - - return profile - - async def is_user_following_for_another_user( - self, - *, - target_user: UserLike, - requested_user: UserLike, - ) -> bool: - return ( - await queries.is_user_following_for_another( - self.connection, - follower_username=requested_user.username, - following_username=target_user.username, - ) - )["is_following"] - - async def add_user_into_followers( - self, - *, - target_user: UserLike, - requested_user: UserLike, - ) -> None: - async with self.connection.transaction(): - await queries.subscribe_user_to_another( - self.connection, - follower_username=requested_user.username, - following_username=target_user.username, - ) - - async def remove_user_from_followers( - self, - *, - target_user: UserLike, - requested_user: UserLike, - ) -> None: - async with self.connection.transaction(): - await queries.unsubscribe_user_from_another( - self.connection, - follower_username=requested_user.username, - following_username=target_user.username, - ) diff --git a/.framework/python/backend/app/db/repositories/tags.py b/.framework/python/backend/app/db/repositories/tags.py deleted file mode 100644 index 5734992..0000000 --- a/.framework/python/backend/app/db/repositories/tags.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import List, Sequence - -from app.db.queries.queries import queries -from app.db.repositories.base import BaseRepository - - -class TagsRepository(BaseRepository): - async def get_all_tags(self) -> List[str]: - tags_row = await queries.get_all_tags(self.connection) - return [tag[0] for tag in tags_row] - - async def create_tags_that_dont_exist(self, *, tags: Sequence[str]) -> None: - await queries.create_new_tags(self.connection, [{"tag": tag} for tag in tags]) diff --git a/.framework/python/backend/app/db/repositories/users.py b/.framework/python/backend/app/db/repositories/users.py deleted file mode 100644 index 0bb18ec..0000000 --- a/.framework/python/backend/app/db/repositories/users.py +++ /dev/null @@ -1,81 +0,0 @@ -from typing import Optional - -from app.db.errors import EntityDoesNotExist -from app.db.queries.queries import queries -from app.db.repositories.base import BaseRepository -from app.models.domain.users import User, UserInDB - - -class UsersRepository(BaseRepository): - async def get_user_by_email(self, *, email: str) -> UserInDB: - user_row = await queries.get_user_by_email(self.connection, email=email) - if user_row: - return UserInDB(**user_row) - - raise EntityDoesNotExist("user with email {0} does not exist".format(email)) - - async def get_user_by_username(self, *, username: str) -> UserInDB: - user_row = await queries.get_user_by_username( - self.connection, - username=username, - ) - if user_row: - return UserInDB(**user_row) - - raise EntityDoesNotExist( - "user with username {0} does not exist".format(username), - ) - - async def create_user( - self, - *, - username: str, - email: str, - password: str, - ) -> UserInDB: - user = UserInDB(username=username, email=email) - user.change_password(password) - - async with self.connection.transaction(): - user_row = await queries.create_new_user( - self.connection, - username=user.username, - email=user.email, - salt=user.salt, - hashed_password=user.hashed_password, - ) - - return user.copy(update=dict(user_row)) - - async def update_user( # noqa: WPS211 - self, - *, - user: User, - username: Optional[str] = None, - email: Optional[str] = None, - password: Optional[str] = None, - bio: Optional[str] = None, - image: Optional[str] = None, - ) -> UserInDB: - user_in_db = await self.get_user_by_username(username=user.username) - - user_in_db.username = username or user_in_db.username - user_in_db.email = email or user_in_db.email - user_in_db.bio = bio or user_in_db.bio - user_in_db.image = image or user_in_db.image - if password: - user_in_db.change_password(password) - - async with self.connection.transaction(): - user_in_db.updated_at = await queries.update_user_by_username( - self.connection, - username=user.username, - new_username=user_in_db.username, - new_email=user_in_db.email, - new_salt=user_in_db.salt, - new_password=user_in_db.hashed_password, - new_bio=user_in_db.bio, - new_image=user_in_db.image, - ) - - return user_in_db diff --git a/.framework/python/backend/app/db/seeds.py b/.framework/python/backend/app/db/seeds.py deleted file mode 100644 index 6509e2d..0000000 --- a/.framework/python/backend/app/db/seeds.py +++ /dev/null @@ -1 +0,0 @@ -print('Please fill the seeds file') diff --git a/.framework/python/backend/app/main.py b/.framework/python/backend/app/main.py deleted file mode 100644 index cff8033..0000000 --- a/.framework/python/backend/app/main.py +++ /dev/null @@ -1,47 +0,0 @@ -from fastapi import FastAPI -from fastapi.exceptions import RequestValidationError -from starlette.exceptions import HTTPException -from starlette.middleware.cors import CORSMiddleware - -from app.api.errors.http_error import http_error_handler -from app.api.errors.validation_error import http422_error_handler -from app.api.routes.api import router as api_router -from app.api.routes.home import router as home_router -from app.core.config import get_app_settings -from app.core.events import create_start_app_handler, create_stop_app_handler - - -def get_application() -> FastAPI: - settings = get_app_settings() - - settings.configure_logging() - - application = FastAPI(**settings.fastapi_kwargs) - - application.add_middleware( - CORSMiddleware, - allow_origins=settings.allowed_hosts, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - application.add_event_handler( - "startup", - create_start_app_handler(application, settings), - ) - application.add_event_handler( - "shutdown", - create_stop_app_handler(application), - ) - - application.add_exception_handler(HTTPException, http_error_handler) - application.add_exception_handler(RequestValidationError, http422_error_handler) - - application.include_router(home_router) - application.include_router(api_router, prefix=settings.api_prefix) - - return application - - -app = get_application() diff --git a/.framework/python/backend/app/models/__init__.py b/.framework/python/backend/app/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/models/common.py b/.framework/python/backend/app/models/common.py deleted file mode 100644 index fdc515b..0000000 --- a/.framework/python/backend/app/models/common.py +++ /dev/null @@ -1,19 +0,0 @@ -import datetime - -from pydantic import BaseModel, Field, validator - - -class DateTimeModelMixin(BaseModel): - created_at: datetime.datetime = None # type: ignore - updated_at: datetime.datetime = None # type: ignore - - @validator("created_at", "updated_at", pre=True) - def default_datetime( - cls, # noqa: N805 - value: datetime.datetime, # noqa: WPS110 - ) -> datetime.datetime: - return value or datetime.datetime.now() - - -class IDModelMixin(BaseModel): - id_: int = Field(0, alias="id") diff --git a/.framework/python/backend/app/models/domain/__init__.py b/.framework/python/backend/app/models/domain/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/models/domain/comments.py b/.framework/python/backend/app/models/domain/comments.py deleted file mode 100644 index c5ec749..0000000 --- a/.framework/python/backend/app/models/domain/comments.py +++ /dev/null @@ -1,8 +0,0 @@ -from app.models.common import DateTimeModelMixin, IDModelMixin -from app.models.domain.profiles import Profile -from app.models.domain.rwmodel import RWModel - - -class Comment(IDModelMixin, DateTimeModelMixin, RWModel): - body: str - seller: Profile diff --git a/.framework/python/backend/app/models/domain/items.py b/.framework/python/backend/app/models/domain/items.py deleted file mode 100644 index 3e95353..0000000 --- a/.framework/python/backend/app/models/domain/items.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import List, Optional - -from app.models.common import DateTimeModelMixin, IDModelMixin -from app.models.domain.profiles import Profile -from app.models.domain.rwmodel import RWModel - - -class Item(IDModelMixin, DateTimeModelMixin, RWModel): - slug: str - title: str - description: str - tags: List[str] - seller: Profile - favorited: bool - favorites_count: int - image: Optional[str] - body: Optional[str] diff --git a/.framework/python/backend/app/models/domain/profiles.py b/.framework/python/backend/app/models/domain/profiles.py deleted file mode 100644 index b1e6ac0..0000000 --- a/.framework/python/backend/app/models/domain/profiles.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Optional - -from app.models.domain.rwmodel import RWModel - - -class Profile(RWModel): - username: str - bio: str = "" - image: Optional[str] = None - following: bool = False diff --git a/.framework/python/backend/app/models/domain/rwmodel.py b/.framework/python/backend/app/models/domain/rwmodel.py deleted file mode 100644 index 1c34f3b..0000000 --- a/.framework/python/backend/app/models/domain/rwmodel.py +++ /dev/null @@ -1,21 +0,0 @@ -import datetime - -from pydantic import BaseConfig, BaseModel - - -def convert_datetime_to_realworld(dt: datetime.datetime) -> str: - return dt.replace(tzinfo=datetime.timezone.utc).isoformat().replace("+00:00", "Z") - - -def convert_field_to_camel_case(string: str) -> str: - return "".join( - word if index == 0 else word.capitalize() - for index, word in enumerate(string.split("_")) - ) - - -class RWModel(BaseModel): - class Config(BaseConfig): - allow_population_by_field_name = True - json_encoders = {datetime.datetime: convert_datetime_to_realworld} - alias_generator = convert_field_to_camel_case diff --git a/.framework/python/backend/app/models/domain/users.py b/.framework/python/backend/app/models/domain/users.py deleted file mode 100644 index 3da2f9d..0000000 --- a/.framework/python/backend/app/models/domain/users.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Optional - -from app.models.common import DateTimeModelMixin, IDModelMixin -from app.models.domain.rwmodel import RWModel -from app.services import security - - -class User(RWModel): - username: str - email: str - bio: str = "" - image: Optional[str] = None - - -class UserInDB(IDModelMixin, DateTimeModelMixin, User): - salt: str = "" - hashed_password: str = "" - - def check_password(self, password: str) -> bool: - return security.verify_password(self.salt + password, self.hashed_password) - - def change_password(self, password: str) -> None: - self.salt = security.generate_salt() - self.hashed_password = security.get_password_hash(self.salt + password) diff --git a/.framework/python/backend/app/models/schemas/__init__.py b/.framework/python/backend/app/models/schemas/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/models/schemas/comments.py b/.framework/python/backend/app/models/schemas/comments.py deleted file mode 100644 index e230697..0000000 --- a/.framework/python/backend/app/models/schemas/comments.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import List - -from app.models.domain.comments import Comment -from app.models.schemas.rwschema import RWSchema - - -class ListOfCommentsInResponse(RWSchema): - comments: List[Comment] - - -class CommentInResponse(RWSchema): - comment: Comment - - -class CommentInCreate(RWSchema): - body: str diff --git a/.framework/python/backend/app/models/schemas/items.py b/.framework/python/backend/app/models/schemas/items.py deleted file mode 100644 index 5c43a59..0000000 --- a/.framework/python/backend/app/models/schemas/items.py +++ /dev/null @@ -1,46 +0,0 @@ -from typing import List, Optional - -from pydantic import BaseModel, Field - -from app.models.domain.items import Item -from app.models.schemas.rwschema import RWSchema - -DEFAULT_ITEMS_LIMIT = 20 -DEFAULT_ITEMS_OFFSET = 0 - - -class ItemForResponse(RWSchema, Item): - tags: List[str] = Field(..., alias="tagList") - - -class ItemInResponse(RWSchema): - item: ItemForResponse - - -class ItemInCreate(RWSchema): - title: str - description: str - body: Optional[str] = None - image: Optional[str] = None - tags: List[str] = Field([], alias="tagList") - - -class ItemInUpdate(RWSchema): - title: Optional[str] = None - description: Optional[str] = None - body: Optional[str] = None - image: Optional[str] = None - tags: Optional[List[str]] = Field(None, alias="tagList") - - -class ListOfItemsInResponse(RWSchema): - items: List[ItemForResponse] - items_count: int - - -class ItemsFilters(BaseModel): - tag: Optional[str] = None - seller: Optional[str] = None - favorited: Optional[str] = None - limit: int = Field(DEFAULT_ITEMS_LIMIT, ge=1) - offset: int = Field(DEFAULT_ITEMS_OFFSET, ge=0) diff --git a/.framework/python/backend/app/models/schemas/jwt.py b/.framework/python/backend/app/models/schemas/jwt.py deleted file mode 100644 index 56d1fa3..0000000 --- a/.framework/python/backend/app/models/schemas/jwt.py +++ /dev/null @@ -1,12 +0,0 @@ -from datetime import datetime - -from pydantic import BaseModel - - -class JWTMeta(BaseModel): - exp: datetime - sub: str - - -class JWTUser(BaseModel): - username: str diff --git a/.framework/python/backend/app/models/schemas/profiles.py b/.framework/python/backend/app/models/schemas/profiles.py deleted file mode 100644 index 5662dfc..0000000 --- a/.framework/python/backend/app/models/schemas/profiles.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic import BaseModel - -from app.models.domain.profiles import Profile - - -class ProfileInResponse(BaseModel): - profile: Profile diff --git a/.framework/python/backend/app/models/schemas/rwschema.py b/.framework/python/backend/app/models/schemas/rwschema.py deleted file mode 100644 index 018ad4b..0000000 --- a/.framework/python/backend/app/models/schemas/rwschema.py +++ /dev/null @@ -1,6 +0,0 @@ -from app.models.domain.rwmodel import RWModel - - -class RWSchema(RWModel): - class Config(RWModel.Config): - orm_mode = True diff --git a/.framework/python/backend/app/models/schemas/tags.py b/.framework/python/backend/app/models/schemas/tags.py deleted file mode 100644 index e9655fb..0000000 --- a/.framework/python/backend/app/models/schemas/tags.py +++ /dev/null @@ -1,7 +0,0 @@ -from typing import List - -from pydantic import BaseModel - - -class TagsInList(BaseModel): - tags: List[str] diff --git a/.framework/python/backend/app/models/schemas/users.py b/.framework/python/backend/app/models/schemas/users.py deleted file mode 100644 index d0f2bba..0000000 --- a/.framework/python/backend/app/models/schemas/users.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel, EmailStr, HttpUrl - -from app.models.domain.users import User -from app.models.schemas.rwschema import RWSchema - - -class UserInLogin(RWSchema): - email: EmailStr - password: str - - -class UserInCreate(UserInLogin): - username: str - - -class UserInUpdate(BaseModel): - username: Optional[str] = None - email: Optional[EmailStr] = None - password: Optional[str] = None - bio: Optional[str] = None - image: Optional[HttpUrl] = None - - -class UserWithToken(User): - token: str - - -class UserInResponse(RWSchema): - user: UserWithToken diff --git a/.framework/python/backend/app/resources/__init__.py b/.framework/python/backend/app/resources/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/resources/strings.py b/.framework/python/backend/app/resources/strings.py deleted file mode 100644 index d7124dd..0000000 --- a/.framework/python/backend/app/resources/strings.py +++ /dev/null @@ -1,25 +0,0 @@ -# API messages - -USER_DOES_NOT_EXIST_ERROR = "user does not exist" -ITEM_DOES_NOT_EXIST_ERROR = "item does not exist" -ITEM_ALREADY_EXISTS = "item already exists" -USER_IS_NOT_SELLER_OF_ITEM = "you are not an seller of this item" - -INCORRECT_LOGIN_INPUT = "incorrect email or password" -USERNAME_TAKEN = "user with this username already exists" -EMAIL_TAKEN = "user with this email already exists" - -UNABLE_TO_FOLLOW_YOURSELF = "user can not follow him self" -UNABLE_TO_UNSUBSCRIBE_FROM_YOURSELF = "user can not unsubscribe from him self" -USER_IS_NOT_FOLLOWED = "you don't follow this user" -USER_IS_ALREADY_FOLLOWED = "you follow this user already" - -WRONG_TOKEN_PREFIX = "unsupported authorization type" # noqa: S105 -MALFORMED_PAYLOAD = "could not validate credentials" - -ITEM_IS_ALREADY_FAVORITED = "you are already marked this items as favorite" -ITEM_IS_NOT_FAVORITED = "item is not favorited" - -COMMENT_DOES_NOT_EXIST = "comment does not exist" - -AUTHENTICATION_REQUIRED = "authentication required" diff --git a/.framework/python/backend/app/services/__init__.py b/.framework/python/backend/app/services/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/python/backend/app/services/authentication.py b/.framework/python/backend/app/services/authentication.py deleted file mode 100644 index 84539a6..0000000 --- a/.framework/python/backend/app/services/authentication.py +++ /dev/null @@ -1,20 +0,0 @@ -from app.db.errors import EntityDoesNotExist -from app.db.repositories.users import UsersRepository - - -async def check_username_is_taken(repo: UsersRepository, username: str) -> bool: - try: - await repo.get_user_by_username(username=username) - except EntityDoesNotExist: - return False - - return True - - -async def check_email_is_taken(repo: UsersRepository, email: str) -> bool: - try: - await repo.get_user_by_email(email=email) - except EntityDoesNotExist: - return False - - return True diff --git a/.framework/python/backend/app/services/event.py b/.framework/python/backend/app/services/event.py deleted file mode 100644 index 1de0618..0000000 --- a/.framework/python/backend/app/services/event.py +++ /dev/null @@ -1,22 +0,0 @@ -import os -import requests -import json - -PATH_TO_WILCO_ID = '../.wilco' -BASE_URL = os.environ.get('ENGINE_BASE_URL') or 'https://engine.wilco.gg' -WILCO_ID = os.environ.get('WILCO_ID') - -if not WILCO_ID and os.path.exists(PATH_TO_WILCO_ID): - with open(PATH_TO_WILCO_ID, 'r') as f: - WILCO_ID = f.read() - -EVENTS_ENDPOINT = f'{BASE_URL}/users/{WILCO_ID}/event' - -def send_event(event, metadata): - headers = { 'Content-type': 'application/json' } - data = { 'event': event, 'metadata': metadata } - try: - res = requests.post(EVENTS_ENDPOINT, data=json.dumps(data), headers=headers) - return res - except Exception as err: - print(f"failed to send event {event} to Wilco engine") diff --git a/.framework/python/backend/app/services/items.py b/.framework/python/backend/app/services/items.py deleted file mode 100644 index b3f6f26..0000000 --- a/.framework/python/backend/app/services/items.py +++ /dev/null @@ -1,23 +0,0 @@ -from slugify import slugify - -from app.db.errors import EntityDoesNotExist -from app.db.repositories.items import ItemsRepository -from app.models.domain.items import Item -from app.models.domain.users import User - - -async def check_item_exists(items_repo: ItemsRepository, slug: str) -> bool: - try: - await items_repo.get_item_by_slug(slug=slug) - except EntityDoesNotExist: - return False - - return True - - -def get_slug_for_item(title: str) -> str: - return slugify(title) - - -def check_user_can_modify_item(item: Item, user: User) -> bool: - return item.seller.username == user.username diff --git a/.framework/python/backend/app/services/jwt.py b/.framework/python/backend/app/services/jwt.py deleted file mode 100644 index 355ecea..0000000 --- a/.framework/python/backend/app/services/jwt.py +++ /dev/null @@ -1,41 +0,0 @@ -from datetime import datetime, timedelta -from typing import Dict - -import jwt -from pydantic import ValidationError - -from app.models.domain.users import User -from app.models.schemas.jwt import JWTMeta, JWTUser - -JWT_SUBJECT = "access" -ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # one week - - -def create_jwt_token( - *, - jwt_content: Dict[str, str], - secret_key: str, - expires_delta: timedelta, -) -> str: - to_encode = jwt_content.copy() - expire = datetime.utcnow() + expires_delta - to_encode.update(JWTMeta(exp=expire, sub=JWT_SUBJECT).dict()) - return jwt.encode(to_encode, secret_key, algorithm=ALGORITHM) - - -def create_access_token_for_user(user: User, secret_key: str) -> str: - return create_jwt_token( - jwt_content=JWTUser(username=user.username).dict(), - secret_key=secret_key, - expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES), - ) - - -def get_username_from_token(token: str, secret_key: str) -> str: - try: - return JWTUser(**jwt.decode(token, secret_key, algorithms=[ALGORITHM])).username - except jwt.PyJWTError as decode_error: - raise ValueError("unable to decode JWT token") from decode_error - except ValidationError as validation_error: - raise ValueError("malformed payload in token") from validation_error diff --git a/.framework/python/backend/app/services/security.py b/.framework/python/backend/app/services/security.py deleted file mode 100644 index 08c523b..0000000 --- a/.framework/python/backend/app/services/security.py +++ /dev/null @@ -1,16 +0,0 @@ -import bcrypt -from passlib.context import CryptContext - -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") - - -def generate_salt() -> str: - return bcrypt.gensalt().decode() - - -def verify_password(plain_password: str, hashed_password: str) -> bool: - return pwd_context.verify(plain_password, hashed_password) - - -def get_password_hash(password: str) -> str: - return pwd_context.hash(password) diff --git a/.framework/python/backend/poetry.lock b/.framework/python/backend/poetry.lock deleted file mode 100644 index 1bbe72f..0000000 --- a/.framework/python/backend/poetry.lock +++ /dev/null @@ -1,2136 +0,0 @@ -[[package]] -name = "aiosql" -version = "3.3.1" -description = "Simple SQL in Python" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -contextlib2 = ">=21.6.0" -typing-extensions = ">=3.7.4,<4" - -[[package]] -name = "alembic" -version = "1.7.6" -description = "A database migration tool for SQLAlchemy." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Mako = "*" -SQLAlchemy = ">=1.3.0" - -[package.extras] -tz = ["python-dateutil"] - -[[package]] -name = "anyio" -version = "3.5.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16)"] - -[[package]] -name = "asgi-lifespan" -version = "1.0.1" -description = "Programmatic startup/shutdown of ASGI apps." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -sniffio = "*" - -[[package]] -name = "asgiref" -version = "3.5.0" -description = "ASGI specs, helper code, and adapters" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] - -[[package]] -name = "astor" -version = "0.8.1" -description = "Read/rewrite/write Python ASTs" -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" - -[[package]] -name = "asyncpg" -version = "0.25.0" -description = "An asyncio PostgreSQL driver" -category = "main" -optional = false -python-versions = ">=3.6.0" - -[package.extras] -dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "pycodestyle (>=2.7.0,<2.8.0)", "flake8 (>=3.9.2,<3.10.0)", "uvloop (>=0.15.3)"] -docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"] -test = ["pycodestyle (>=2.7.0,<2.8.0)", "flake8 (>=3.9.2,<3.10.0)", "uvloop (>=0.15.3)"] - -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "attrs" -version = "21.4.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] - -[[package]] -name = "autoflake" -version = "1.4" -description = "Removes unused imports and unused variables" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -pyflakes = ">=1.1.0" - -[[package]] -name = "bandit" -version = "1.7.2" -description = "Security oriented static analyser for python code." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" -PyYAML = ">=5.3.1" -stevedore = ">=1.20.0" - -[package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] -yaml = ["pyyaml"] - -[[package]] -name = "bcrypt" -version = "3.2.0" -description = "Modern password hashing for your software and your servers" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -cffi = ">=1.1" -six = ">=1.4.1" - -[package.extras] -tests = ["pytest (>=3.2.1,!=3.3.0)"] -typecheck = ["mypy"] - -[[package]] -name = "black" -version = "22.1.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = ">=1.1.0" -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "certifi" -version = "2021.10.8" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "cffi" -version = "1.15.0" -description = "Foreign Function Interface for Python calling C code." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "2.0.11" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode_backport = ["unicodedata2"] - -[[package]] -name = "click" -version = "8.0.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "contextlib2" -version = "21.6.0" -description = "Backports and enhancements for the contextlib module" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "coverage" -version = "6.4.1" -description = "Code coverage measurement for Python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli"] - -[[package]] -name = "darglint" -version = "1.8.1" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" - -[[package]] -name = "databases" -version = "0.5.5" -description = "Async database support for Python." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -sqlalchemy = ">=1.4,<1.5" - -[package.extras] -mysql = ["aiomysql"] -mysql_asyncmy = ["asyncmy"] -postgresql = ["asyncpg"] -postgresql_aiopg = ["aiopg"] -sqlite = ["aiosqlite"] - -[[package]] -name = "dnspython" -version = "2.2.0" -description = "DNS toolkit" -category = "main" -optional = false -python-versions = ">=3.6,<4.0" - -[package.extras] -dnssec = ["cryptography (>=2.6,<37.0)"] -curio = ["curio (>=1.2,<2.0)", "sniffio (>=1.1,<2.0)"] -doh = ["h2 (>=4.1.0)", "httpx (>=0.21.1)", "requests (>=2.23.0,<3.0.0)", "requests-toolbelt (>=0.9.1,<0.10.0)"] -idna = ["idna (>=2.1,<4.0)"] -trio = ["trio (>=0.14,<0.20)"] -wmi = ["wmi (>=1.5.1,<2.0.0)"] - -[[package]] -name = "docutils" -version = "0.18.1" -description = "Docutils -- Python Documentation Utilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "email-validator" -version = "1.1.3" -description = "A robust email syntax and deliverability validation library for Python 2.x/3.x." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.dependencies] -dnspython = ">=1.15.0" -idna = ">=2.0.0" - -[[package]] -name = "eradicate" -version = "2.0.0" -description = "Removes commented-out code." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "execnet" -version = "1.9.0" -description = "execnet: rapid multi-Python deployment" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -testing = ["pre-commit"] - -[[package]] -name = "fastapi" -version = "0.73.0" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[package.dependencies] -pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" -starlette = "0.17.1" - -[package.extras] -all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<6.0.0)", "ujson (>=4.0.1,<5.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.16.0)"] -dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.16.0)"] -doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer-cli (>=0.0.12,<0.0.13)", "pyyaml (>=5.3.1,<6.0.0)"] -test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==21.9b0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,<5.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==0.1.1)", "types-orjson (==3.6.0)", "types-dataclasses (==0.1.7)"] - -[[package]] -name = "flake8" -version = "3.9.2" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.7.0,<2.8.0" -pyflakes = ">=2.3.0,<2.4.0" - -[[package]] -name = "flake8-bandit" -version = "2.1.2" -description = "Automated security testing with bandit and flake8." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -bandit = "*" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" - -[[package]] -name = "flake8-broken-line" -version = "0.3.0" -description = "Flake8 plugin to forbid backslashes for line breaks" -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" - -[package.dependencies] -flake8 = ">=3.5,<4.0" - -[[package]] -name = "flake8-bugbear" -version = "21.11.29" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=3.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] - -[[package]] -name = "flake8-commas" -version = "2.1.0" -description = "Flake8 lint for trailing commas." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=2" - -[[package]] -name = "flake8-comprehensions" -version = "3.8.0" -description = "A flake8 plugin to help you write better list/set/dict comprehensions." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -flake8 = ">=3.0,<3.2.0 || >3.2.0" - -[[package]] -name = "flake8-debugger" -version = "4.0.0" -description = "ipdb/pdb statement checker plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -flake8 = ">=3.0" -pycodestyle = "*" -six = "*" - -[[package]] -name = "flake8-docstrings" -version = "1.6.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[[package]] -name = "flake8-eradicate" -version = "1.2.0" -description = "Flake8 plugin to find commented out code" -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" - -[package.dependencies] -attrs = "*" -eradicate = ">=2.0,<3.0" -flake8 = ">=3.5,<5" - -[[package]] -name = "flake8-fixme" -version = "1.1.1" -description = "Check for FIXME, TODO and other temporary developer notes. Plugin for flake8." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "flake8-isort" -version = "4.1.1" -description = "flake8 plugin that integrates isort ." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = ">=3.2.1,<5" -isort = ">=4.3.5,<6" -testfixtures = ">=6.8.0,<7" - -[package.extras] -test = ["pytest-cov"] - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flake8-quotes" -version = "3.3.1" -description = "Flake8 lint for quotes." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flake8-rst-docstrings" -version = "0.2.5" -description = "Python docstring reStructuredText (RST) validator" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -flake8 = ">=3.0.0" -pygments = "*" -restructuredtext-lint = "*" - -[[package]] -name = "flake8-string-format" -version = "0.3.0" -description = "string format checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "gitdb" -version = "4.0.9" -description = "Git Object Database" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.26" -description = "GitPython is a python library used to interact with Git repositories" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[[package]] -name = "greenlet" -version = "1.1.2" -description = "Lightweight in-process concurrent programming" -category = "main" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" - -[package.extras] -docs = ["sphinx"] - -[[package]] -name = "gunicorn" -version = "20.1.0" -description = "WSGI HTTP Server for UNIX" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -eventlet = ["eventlet (>=0.24.1)"] -gevent = ["gevent (>=1.4.0)"] -setproctitle = ["setproctitle"] -tornado = ["tornado (>=0.2)"] - -[[package]] -name = "h11" -version = "0.12.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "httpcore" -version = "0.14.7" -description = "A minimal low-level HTTP client." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -anyio = ">=3.0.0,<4.0.0" -certifi = "*" -h11 = ">=0.11,<0.13" -sniffio = ">=1.0.0,<2.0.0" - -[package.extras] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] - -[[package]] -name = "httpx" -version = "0.22.0" -description = "The next generation HTTP client." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -certifi = "*" -charset-normalizer = "*" -httpcore = ">=0.14.5,<0.15.0" -rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} -sniffio = "*" - -[package.extras] -brotli = ["brotlicffi", "brotli"] -cli = ["click (>=8.0.0,<9.0.0)", "rich (>=10.0.0,<11.0.0)", "pygments (>=2.0.0,<3.0.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] - -[[package]] -name = "idna" -version = "3.3" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "isort" -version = "5.10.1" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.6.1,<4.0" - -[package.extras] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] -requirements_deprecated_finder = ["pipreqs", "pip-api"] -colors = ["colorama (>=0.4.3,<0.5.0)"] -plugins = ["setuptools"] - -[[package]] -name = "loguru" -version = "0.6.0" -description = "Python logging made (stupidly) simple" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "black (>=19.10b0)", "isort (>=5.1.1)", "Sphinx (>=4.1.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)"] - -[[package]] -name = "mako" -version = "1.1.6" -description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -MarkupSafe = ">=0.9.2" - -[package.extras] -babel = ["babel"] -lingua = ["lingua"] - -[[package]] -name = "markupsafe" -version = "2.0.1" -description = "Safely add untrusted strings to HTML/XML markup." -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "mypy" -version = "0.931" -description = "Optional static typing for Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -mypy-extensions = ">=0.4.3" -tomli = ">=1.1.0" -typing-extensions = ">=3.10" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<2)"] - -[[package]] -name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "packaging" -version = "21.3" -description = "Core utilities for Python packages" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" - -[[package]] -name = "passlib" -version = "1.7.4" -description = "comprehensive password hashing framework supporting over 30 schemes" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -bcrypt = {version = ">=3.1.0", optional = true, markers = "extra == \"bcrypt\""} - -[package.extras] -argon2 = ["argon2-cffi (>=18.2.0)"] -bcrypt = ["bcrypt (>=3.1.0)"] -build_docs = ["sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)", "cloud-sptheme (>=1.10.1)"] -totp = ["cryptography"] - -[[package]] -name = "pathspec" -version = "0.9.0" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[[package]] -name = "pbr" -version = "5.8.1" -description = "Python Build Reasonableness" -category = "dev" -optional = false -python-versions = ">=2.6" - -[[package]] -name = "pep8-naming" -version = "0.11.1" -description = "Check PEP-8 naming conventions, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -flake8-polyfill = ">=1.0.2,<2" - -[[package]] -name = "platformdirs" -version = "2.4.1" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] - -[[package]] -name = "pluggy" -version = "1.0.0" -description = "plugin and hook calling mechanisms for python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "psycopg2-binary" -version = "2.9.3" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pycodestyle" -version = "2.7.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pydantic" -version = "1.9.0" -description = "Data validation and settings management using python 3.6 type hinting" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[package.dependencies] -email-validator = {version = ">=1.0.3", optional = true, markers = "extra == \"email\""} -python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""} -typing-extensions = ">=3.7.4.3" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pydocstyle" -version = "6.1.1" -description = "Python docstring style checker" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -snowballstemmer = "*" - -[package.extras] -toml = ["toml"] - -[[package]] -name = "pyflakes" -version = "2.3.1" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pygments" -version = "2.11.2" -description = "Pygments is a syntax highlighting package written in Python." -category = "dev" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "pyjwt" -version = "2.3.0" -description = "JSON Web Token implementation in Python" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -crypto = ["cryptography (>=3.3.1)"] -dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"] - -[[package]] -name = "pyparsing" -version = "3.0.7" -description = "Python parsing module" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pypika" -version = "0.48.8" -description = "A SQL query builder API for Python" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "pytest" -version = "7.0.0" -description = "pytest: simple powerful testing with Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.18.0" -description = "Pytest support for asyncio" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -pytest = ">=6.1.0" - -[package.extras] -testing = ["coverage (==6.2)", "hypothesis (>=5.7.1)", "flaky (>=3.5.0)", "mypy (==0.931)"] - -[[package]] -name = "pytest-cov" -version = "3.0.0" -description = "Pytest plugin for measuring coverage." -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] - -[[package]] -name = "pytest-env" -version = "0.6.2" -description = "py.test plugin that allows you to add environment variables." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -pytest = ">=2.6.0" - -[[package]] -name = "pytest-forked" -version = "1.4.0" -description = "run tests in isolated forked subprocesses" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -py = "*" -pytest = ">=3.10" - -[[package]] -name = "pytest-xdist" -version = "2.5.0" -description = "pytest xdist plugin for distributed testing and loop-on-failing modes" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -execnet = ">=1.1" -pytest = ">=6.2.0" -pytest-forked = "*" - -[package.extras] -psutil = ["psutil (>=3.0)"] -setproctitle = ["setproctitle"] -testing = ["filelock"] - -[[package]] -name = "python-dotenv" -version = "0.19.2" -description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "python-slugify" -version = "5.0.2" -description = "A Python Slugify application that handles Unicode" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -text-unidecode = ">=1.3" - -[package.extras] -unidecode = ["Unidecode (>=1.1.1)"] - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "requests" -version = "2.28.0" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=3.7, <4" - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2.0.0,<2.1.0" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] - -[[package]] -name = "restructuredtext-lint" -version = "1.3.2" -description = "reStructuredText linter" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -docutils = ">=0.11,<1.0" - -[[package]] -name = "rfc3986" -version = "1.5.0" -description = "Validating URI References per RFC 3986" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} - -[package.extras] -idna2008 = ["idna"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "smmap" -version = "5.0.0" -description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "sniffio" -version = "1.2.0" -description = "Sniff out which async library your code is running under" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "sqlalchemy" -version = "1.4.31" -description = "Database Abstraction Library" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} - -[package.extras] -aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] -aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3)"] -mariadb_connector = ["mariadb (>=1.0.1)"] -mssql = ["pyodbc"] -mssql_pymssql = ["pymssql"] -mssql_pyodbc = ["pyodbc"] -mypy = ["sqlalchemy2-stubs", "mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] -mysql_connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] -postgresql_pg8000 = ["pg8000 (>=1.16.6)"] -postgresql_psycopg2binary = ["psycopg2-binary"] -postgresql_psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql (<1)", "pymysql"] -sqlcipher = ["sqlcipher3-binary"] - -[[package]] -name = "starlette" -version = "0.17.1" -description = "The little ASGI library that shines." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -anyio = ">=3.0.0,<4" - -[package.extras] -full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] - -[[package]] -name = "stevedore" -version = "3.5.0" -description = "Manage dynamic plugins for Python applications" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pbr = ">=2.0.0,<2.1.0 || >2.1.0" - -[[package]] -name = "testfixtures" -version = "6.18.3" -description = "A collection of helpers and mock objects for unit tests and doc tests." -category = "dev" -optional = false -python-versions = "*" - -[package.extras] -build = ["setuptools-git", "wheel", "twine"] -docs = ["sphinx", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] -test = ["pytest (>=3.6)", "pytest-cov", "pytest-django", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] - -[[package]] -name = "text-unidecode" -version = "1.3" -description = "The most basic Text::Unidecode port" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "tomli" -version = "2.0.0" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "unidecode" -version = "1.3.2" -description = "ASCII transliterations of Unicode text" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "urllib3" -version = "1.26.9" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" - -[package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "uvicorn" -version = "0.17.4" -description = "The lightning-fast ASGI server." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -asgiref = ">=3.4.0" -click = ">=7.0" -h11 = ">=0.8" - -[package.extras] -standard = ["websockets (>=10.0)", "httptools (>=0.2.0,<0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] - -[[package]] -name = "wemake-python-styleguide" -version = "0.16.0" -description = "The strictest and most opinionated python linter ever" -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" - -[package.dependencies] -astor = ">=0.8,<0.9" -attrs = "*" -darglint = ">=1.2,<2.0" -flake8 = ">=3.7,<5" -flake8-bandit = ">=2.1,<3.0" -flake8-broken-line = ">=0.3,<0.5" -flake8-bugbear = ">=20.1,<22.0" -flake8-commas = ">=2.0,<3.0" -flake8-comprehensions = ">=3.1,<4.0" -flake8-debugger = ">=4.0,<5.0" -flake8-docstrings = ">=1.3,<2.0" -flake8-eradicate = ">=1.0,<2.0" -flake8-isort = ">=4.0,<5.0" -flake8-quotes = ">=3.0,<4.0" -flake8-rst-docstrings = ">=0.2.3,<0.3.0" -flake8-string-format = ">=0.3,<0.4" -pep8-naming = ">=0.11,<0.13" -pygments = ">=2.4,<3.0" -typing_extensions = ">=3.6,<5.0" - -[[package]] -name = "win32-setctime" -version = "1.1.0" -description = "A small Python utility to set file creation time on Windows" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] - -[metadata] -lock-version = "1.1" -python-versions = "3.9.13" -content-hash = "cedb44c416663f147800d5ee734ba784fc0113120f236dc9675394eaadad0eca" - -[metadata.files] -aiosql = [ - {file = "aiosql-3.3.1-py3-none-any.whl", hash = "sha256:467067f2d237e2ccc47a3f651ae6bd128d89287a5dbf1357c065c9be37947cbc"}, - {file = "aiosql-3.3.1.tar.gz", hash = "sha256:e7144b0e96c2783b79002657497b3a16ee41068290adc1e89cf08cb3974c76fa"}, -] -alembic = [ - {file = "alembic-1.7.6-py3-none-any.whl", hash = "sha256:ad842f2c3ab5c5d4861232730779c05e33db4ba880a08b85eb505e87c01095bc"}, - {file = "alembic-1.7.6.tar.gz", hash = "sha256:6c0c05e9768a896d804387e20b299880fe01bc56484246b0dffe8075d6d3d847"}, -] -anyio = [ - {file = "anyio-3.5.0-py3-none-any.whl", hash = "sha256:b5fa16c5ff93fa1046f2eeb5bbff2dad4d3514d6cda61d02816dba34fa8c3c2e"}, - {file = "anyio-3.5.0.tar.gz", hash = "sha256:a0aeffe2fb1fdf374a8e4b471444f0f3ac4fb9f5a5b542b48824475e0042a5a6"}, -] -asgi-lifespan = [ - {file = "asgi-lifespan-1.0.1.tar.gz", hash = "sha256:9a33e7da2073c4764bc79bd6136501d6c42f60e3d2168ba71235e84122eadb7f"}, - {file = "asgi_lifespan-1.0.1-py3-none-any.whl", hash = "sha256:9ea969dc5eb5cf08e52c08dce6f61afcadd28112e72d81c972b1d8eb8691ab53"}, -] -asgiref = [ - {file = "asgiref-3.5.0-py3-none-any.whl", hash = "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"}, - {file = "asgiref-3.5.0.tar.gz", hash = "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0"}, -] -astor = [ - {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, - {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, -] -asyncpg = [ - {file = "asyncpg-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf5e3408a14a17d480f36ebaf0401a12ff6ae5457fdf45e4e2775c51cc9517d3"}, - {file = "asyncpg-0.25.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2bc197fc4aca2fd24f60241057998124012469d2e414aed3f992579db0c88e3a"}, - {file = "asyncpg-0.25.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a70783f6ffa34cc7dd2de20a873181414a34fd35a4a208a1f1a7f9f695e4ec4"}, - {file = "asyncpg-0.25.0-cp310-cp310-win32.whl", hash = "sha256:43cde84e996a3afe75f325a68300093425c2f47d340c0fc8912765cf24a1c095"}, - {file = "asyncpg-0.25.0-cp310-cp310-win_amd64.whl", hash = "sha256:56d88d7ef4341412cd9c68efba323a4519c916979ba91b95d4c08799d2ff0c09"}, - {file = "asyncpg-0.25.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a84d30e6f850bac0876990bcd207362778e2208df0bee8be8da9f1558255e634"}, - {file = "asyncpg-0.25.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:beaecc52ad39614f6ca2e48c3ca15d56e24a2c15cbfdcb764a4320cc45f02fd5"}, - {file = "asyncpg-0.25.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:6f8f5fc975246eda83da8031a14004b9197f510c41511018e7b1bedde6968e92"}, - {file = "asyncpg-0.25.0-cp36-cp36m-win32.whl", hash = "sha256:ddb4c3263a8d63dcde3d2c4ac1c25206bfeb31fa83bd70fd539e10f87739dee4"}, - {file = "asyncpg-0.25.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bf6dc9b55b9113f39eaa2057337ce3f9ef7de99a053b8a16360395ce588925cd"}, - {file = "asyncpg-0.25.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:acb311722352152936e58a8ee3c5b8e791b24e84cd7d777c414ff05b3530ca68"}, - {file = "asyncpg-0.25.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a61fb196ce4dae2f2fa26eb20a778db21bbee484d2e798cb3cc988de13bdd1b"}, - {file = "asyncpg-0.25.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2633331cbc8429030b4f20f712f8d0fbba57fa8555ee9b2f45f981b81328b256"}, - {file = "asyncpg-0.25.0-cp37-cp37m-win32.whl", hash = "sha256:863d36eba4a7caa853fd7d83fad5fd5306f050cc2fe6e54fbe10cdb30420e5e9"}, - {file = "asyncpg-0.25.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fe471ccd915b739ca65e2e4dbd92a11b44a5b37f2e38f70827a1c147dafe0fa8"}, - {file = "asyncpg-0.25.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:72a1e12ea0cf7c1e02794b697e3ca967b2360eaa2ce5d4bfdd8604ec2d6b774b"}, - {file = "asyncpg-0.25.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4327f691b1bdb222df27841938b3e04c14068166b3a97491bec2cb982f49f03e"}, - {file = "asyncpg-0.25.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:739bbd7f89a2b2f6bc44cb8bf967dab12c5bc714fcbe96e68d512be45ecdf962"}, - {file = "asyncpg-0.25.0-cp38-cp38-win32.whl", hash = "sha256:18d49e2d93a7139a2fdbd113e320cc47075049997268a61bfbe0dde680c55471"}, - {file = "asyncpg-0.25.0-cp38-cp38-win_amd64.whl", hash = "sha256:191fe6341385b7fdea7dbdcf47fd6db3fd198827dcc1f2b228476d13c05a03c6"}, - {file = "asyncpg-0.25.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:52fab7f1b2c29e187dd8781fce896249500cf055b63471ad66332e537e9b5f7e"}, - {file = "asyncpg-0.25.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a738f1b2876f30d710d3dc1e7858160a0afe1603ba16bf5f391f5316eb0ed855"}, - {file = "asyncpg-0.25.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4105f57ad1e8fbc8b1e535d8fcefa6ce6c71081228f08680c6dea24384ff0e"}, - {file = "asyncpg-0.25.0-cp39-cp39-win32.whl", hash = "sha256:f55918ded7b85723a5eaeb34e86e7b9280d4474be67df853ab5a7fa0cc7c6bf2"}, - {file = "asyncpg-0.25.0-cp39-cp39-win_amd64.whl", hash = "sha256:649e2966d98cc48d0646d9a4e29abecd8b59d38d55c256d5c857f6b27b7407ac"}, - {file = "asyncpg-0.25.0.tar.gz", hash = "sha256:63f8e6a69733b285497c2855464a34de657f2cccd25aeaeeb5071872e9382540"}, -] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] -attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, -] -autoflake = [ - {file = "autoflake-1.4.tar.gz", hash = "sha256:61a353012cff6ab94ca062823d1fb2f692c4acda51c76ff83a8d77915fba51ea"}, -] -bandit = [ - {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, - {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, -] -bcrypt = [ - {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b589229207630484aefe5899122fb938a5b017b0f4349f769b8c13e78d99a8fd"}, - {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"}, - {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"}, - {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"}, - {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"}, - {file = "bcrypt-3.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a0584a92329210fcd75eb8a3250c5a941633f8bfaf2a18f81009b097732839b7"}, - {file = "bcrypt-3.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:56e5da069a76470679f312a7d3d23deb3ac4519991a0361abc11da837087b61d"}, - {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"}, - {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"}, - {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"}, -] -black = [ - {file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"}, - {file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"}, - {file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"}, - {file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"}, - {file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"}, - {file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"}, - {file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"}, - {file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"}, - {file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"}, - {file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"}, - {file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"}, - {file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"}, - {file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"}, - {file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"}, - {file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"}, - {file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"}, - {file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"}, - {file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"}, - {file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"}, - {file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"}, - {file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"}, - {file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"}, - {file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"}, -] -certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, -] -cffi = [ - {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, - {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, - {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, - {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, - {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, - {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, - {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, - {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, - {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, - {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, - {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, - {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, - {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, - {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, - {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, - {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, - {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, - {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, - {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, - {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, - {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, - {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, - {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, - {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, - {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, - {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"}, - {file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"}, -] -click = [ - {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, - {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -contextlib2 = [ - {file = "contextlib2-21.6.0-py2.py3-none-any.whl", hash = "sha256:3fbdb64466afd23abaf6c977627b75b6139a5a3e8ce38405c5b413aed7a0471f"}, - {file = "contextlib2-21.6.0.tar.gz", hash = "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869"}, -] -coverage = [ - {file = "coverage-6.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b"}, - {file = "coverage-6.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068"}, - {file = "coverage-6.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4"}, - {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84"}, - {file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad"}, - {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc"}, - {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749"}, - {file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4"}, - {file = "coverage-6.4.1-cp310-cp310-win32.whl", hash = "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df"}, - {file = "coverage-6.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6"}, - {file = "coverage-6.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46"}, - {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982"}, - {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4"}, - {file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb"}, - {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b"}, - {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3"}, - {file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6"}, - {file = "coverage-6.4.1-cp37-cp37m-win32.whl", hash = "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e"}, - {file = "coverage-6.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28"}, - {file = "coverage-6.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54"}, - {file = "coverage-6.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9"}, - {file = "coverage-6.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13"}, - {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9"}, - {file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605"}, - {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d"}, - {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428"}, - {file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83"}, - {file = "coverage-6.4.1-cp38-cp38-win32.whl", hash = "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b"}, - {file = "coverage-6.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c"}, - {file = "coverage-6.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df"}, - {file = "coverage-6.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d"}, - {file = "coverage-6.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4"}, - {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3"}, - {file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3"}, - {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8"}, - {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72"}, - {file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264"}, - {file = "coverage-6.4.1-cp39-cp39-win32.whl", hash = "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9"}, - {file = "coverage-6.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397"}, - {file = "coverage-6.4.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815"}, - {file = "coverage-6.4.1.tar.gz", hash = "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c"}, -] -darglint = [ - {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, - {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, -] -databases = [ - {file = "databases-0.5.5-py3-none-any.whl", hash = "sha256:97d9b9647216d1ab53ca61c059412b5c7b6e1f0bf8ce985477982ebcc7f278f3"}, - {file = "databases-0.5.5.tar.gz", hash = "sha256:02c6b016c1c951c21cca281dc8e2e002c60dc44026c0084aabbd8c37514aeb37"}, -] -dnspython = [ - {file = "dnspython-2.2.0-py3-none-any.whl", hash = "sha256:081649da27ced5e75709a1ee542136eaba9842a0fe4c03da4fb0a3d3ed1f3c44"}, - {file = "dnspython-2.2.0.tar.gz", hash = "sha256:e79351e032d0b606b98d38a4b0e6e2275b31a5b85c873e587cc11b73aca026d6"}, -] -docutils = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, -] -email-validator = [ - {file = "email_validator-1.1.3-py2.py3-none-any.whl", hash = "sha256:5675c8ceb7106a37e40e2698a57c056756bf3f272cfa8682a4f87ebd95d8440b"}, - {file = "email_validator-1.1.3.tar.gz", hash = "sha256:aa237a65f6f4da067119b7df3f13e89c25c051327b2b5b66dc075f33d62480d7"}, -] -eradicate = [ - {file = "eradicate-2.0.0.tar.gz", hash = "sha256:27434596f2c5314cc9b31410c93d8f7e8885747399773cd088d3adea647a60c8"}, -] -execnet = [ - {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, - {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, -] -fastapi = [ - {file = "fastapi-0.73.0-py3-none-any.whl", hash = "sha256:f0a618aff5f6942862f2d3f20f39b1c037e33314d1b8207fd1c3a2cca76dfd8c"}, - {file = "fastapi-0.73.0.tar.gz", hash = "sha256:dcfee92a7f9a72b5d4b7ca364bd2b009f8fc10d95ed5769be20e94f39f7e5a15"}, -] -flake8 = [ - {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, - {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, -] -flake8-bandit = [ - {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, -] -flake8-broken-line = [ - {file = "flake8-broken-line-0.3.0.tar.gz", hash = "sha256:f74e052833324a9e5f0055032f7ccc54b23faabafe5a26241c2f977e70b10b50"}, - {file = "flake8_broken_line-0.3.0-py3-none-any.whl", hash = "sha256:611f79c7f27118e7e5d3dc098ef7681c40aeadf23783700c5dbee840d2baf3af"}, -] -flake8-bugbear = [ - {file = "flake8-bugbear-21.11.29.tar.gz", hash = "sha256:8b04cb2fafc6a78e1a9d873bd3988e4282f7959bb6b0d7c1ae648ec09b937a7b"}, - {file = "flake8_bugbear-21.11.29-py36.py37.py38-none-any.whl", hash = "sha256:179e41ddae5de5e3c20d1f61736feeb234e70958fbb56ab3c28a67739c8e9a82"}, -] -flake8-commas = [ - {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, - {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, -] -flake8-comprehensions = [ - {file = "flake8-comprehensions-3.8.0.tar.gz", hash = "sha256:8e108707637b1d13734f38e03435984f6b7854fa6b5a4e34f93e69534be8e521"}, - {file = "flake8_comprehensions-3.8.0-py3-none-any.whl", hash = "sha256:9406314803abe1193c064544ab14fdc43c58424c0882f6ff8a581eb73fc9bb58"}, -] -flake8-debugger = [ - {file = "flake8-debugger-4.0.0.tar.gz", hash = "sha256:e43dc777f7db1481db473210101ec2df2bd39a45b149d7218a618e954177eda6"}, - {file = "flake8_debugger-4.0.0-py3-none-any.whl", hash = "sha256:82e64faa72e18d1bdd0000407502ebb8ecffa7bc027c62b9d4110ce27c091032"}, -] -flake8-docstrings = [ - {file = "flake8-docstrings-1.6.0.tar.gz", hash = "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"}, - {file = "flake8_docstrings-1.6.0-py2.py3-none-any.whl", hash = "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde"}, -] -flake8-eradicate = [ - {file = "flake8-eradicate-1.2.0.tar.gz", hash = "sha256:acaa1b6839ff00d284b805c432fdfa6047262bd15a5504ec945797e87b4de1fa"}, - {file = "flake8_eradicate-1.2.0-py3-none-any.whl", hash = "sha256:51dc660d0c1c1ed93af0f813540bbbf72ab2d3466c14e3f3bac371c618b6042f"}, -] -flake8-fixme = [ - {file = "flake8-fixme-1.1.1.tar.gz", hash = "sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a"}, - {file = "flake8_fixme-1.1.1-py2.py3-none-any.whl", hash = "sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac"}, -] -flake8-isort = [ - {file = "flake8-isort-4.1.1.tar.gz", hash = "sha256:d814304ab70e6e58859bc5c3e221e2e6e71c958e7005239202fee19c24f82717"}, - {file = "flake8_isort-4.1.1-py3-none-any.whl", hash = "sha256:c4e8b6dcb7be9b71a02e6e5d4196cefcef0f3447be51e82730fb336fff164949"}, -] -flake8-polyfill = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] -flake8-quotes = [ - {file = "flake8-quotes-3.3.1.tar.gz", hash = "sha256:633adca6fb8a08131536af0d750b44d6985b9aba46f498871e21588c3e6f525a"}, -] -flake8-rst-docstrings = [ - {file = "flake8-rst-docstrings-0.2.5.tar.gz", hash = "sha256:4fe93f997dea45d9d3c8bd220f12f0b6c359948fb943b5b48021a3f927edd816"}, - {file = "flake8_rst_docstrings-0.2.5-py3-none-any.whl", hash = "sha256:b99d9041b769b857efe45a448dc8c71b1bb311f9cacbdac5de82f96498105082"}, -] -flake8-string-format = [ - {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, - {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, -] -gitdb = [ - {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, - {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, -] -gitpython = [ - {file = "GitPython-3.1.26-py3-none-any.whl", hash = "sha256:26ac35c212d1f7b16036361ca5cff3ec66e11753a0d677fb6c48fa4e1a9dd8d6"}, - {file = "GitPython-3.1.26.tar.gz", hash = "sha256:fc8868f63a2e6d268fb25f481995ba185a85a66fcad126f039323ff6635669ee"}, -] -greenlet = [ - {file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"}, - {file = "greenlet-1.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a"}, - {file = "greenlet-1.1.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d"}, - {file = "greenlet-1.1.2-cp27-cp27m-win32.whl", hash = "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713"}, - {file = "greenlet-1.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40"}, - {file = "greenlet-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d"}, - {file = "greenlet-1.1.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8"}, - {file = "greenlet-1.1.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d"}, - {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497"}, - {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1"}, - {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58"}, - {file = "greenlet-1.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b336501a05e13b616ef81ce329c0e09ac5ed8c732d9ba7e3e983fcc1a9e86965"}, - {file = "greenlet-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708"}, - {file = "greenlet-1.1.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23"}, - {file = "greenlet-1.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee"}, - {file = "greenlet-1.1.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c"}, - {file = "greenlet-1.1.2-cp35-cp35m-win32.whl", hash = "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963"}, - {file = "greenlet-1.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e"}, - {file = "greenlet-1.1.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073"}, - {file = "greenlet-1.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c"}, - {file = "greenlet-1.1.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e"}, - {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce"}, - {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08"}, - {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168"}, - {file = "greenlet-1.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b8c008de9d0daba7b6666aa5bbfdc23dcd78cafc33997c9b7741ff6353bafb7f"}, - {file = "greenlet-1.1.2-cp36-cp36m-win32.whl", hash = "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa"}, - {file = "greenlet-1.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d"}, - {file = "greenlet-1.1.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4"}, - {file = "greenlet-1.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b"}, - {file = "greenlet-1.1.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c"}, - {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1"}, - {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28"}, - {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5"}, - {file = "greenlet-1.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c5d5b35f789a030ebb95bff352f1d27a93d81069f2adb3182d99882e095cefe"}, - {file = "greenlet-1.1.2-cp37-cp37m-win32.whl", hash = "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc"}, - {file = "greenlet-1.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06"}, - {file = "greenlet-1.1.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0"}, - {file = "greenlet-1.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627"}, - {file = "greenlet-1.1.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478"}, - {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43"}, - {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711"}, - {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b"}, - {file = "greenlet-1.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2bde6792f313f4e918caabc46532aa64aa27a0db05d75b20edfc5c6f46479de2"}, - {file = "greenlet-1.1.2-cp38-cp38-win32.whl", hash = "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd"}, - {file = "greenlet-1.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3"}, - {file = "greenlet-1.1.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67"}, - {file = "greenlet-1.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab"}, - {file = "greenlet-1.1.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5"}, - {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88"}, - {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b"}, - {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3"}, - {file = "greenlet-1.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0051c6f1f27cb756ffc0ffbac7d2cd48cb0362ac1736871399a739b2885134d3"}, - {file = "greenlet-1.1.2-cp39-cp39-win32.whl", hash = "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf"}, - {file = "greenlet-1.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd"}, - {file = "greenlet-1.1.2.tar.gz", hash = "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a"}, -] -gunicorn = [ - {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, - {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, -] -h11 = [ - {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, - {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, -] -httpcore = [ - {file = "httpcore-0.14.7-py3-none-any.whl", hash = "sha256:47d772f754359e56dd9d892d9593b6f9870a37aeb8ba51e9a88b09b3d68cfade"}, - {file = "httpcore-0.14.7.tar.gz", hash = "sha256:7503ec1c0f559066e7e39bc4003fd2ce023d01cf51793e3c173b864eb456ead1"}, -] -httpx = [ - {file = "httpx-0.22.0-py3-none-any.whl", hash = "sha256:e35e83d1d2b9b2a609ef367cc4c1e66fd80b750348b20cc9e19d1952fc2ca3f6"}, - {file = "httpx-0.22.0.tar.gz", hash = "sha256:d8e778f76d9bbd46af49e7f062467e3157a5a3d2ae4876a4bbfd8a51ed9c9cb4"}, -] -idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -isort = [ - {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, - {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, -] -loguru = [ - {file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"}, - {file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"}, -] -mako = [ - {file = "Mako-1.1.6-py2.py3-none-any.whl", hash = "sha256:afaf8e515d075b22fad7d7b8b30e4a1c90624ff2f3733a06ec125f5a5f043a57"}, - {file = "Mako-1.1.6.tar.gz", hash = "sha256:4e9e345a41924a954251b95b4b28e14a301145b544901332e658907a7464b6b2"}, -] -markupsafe = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, - {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, -] -mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] -mypy = [ - {file = "mypy-0.931-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a"}, - {file = "mypy-0.931-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00"}, - {file = "mypy-0.931-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714"}, - {file = "mypy-0.931-cp310-cp310-win_amd64.whl", hash = "sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc"}, - {file = "mypy-0.931-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d"}, - {file = "mypy-0.931-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d"}, - {file = "mypy-0.931-cp36-cp36m-win_amd64.whl", hash = "sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c"}, - {file = "mypy-0.931-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0"}, - {file = "mypy-0.931-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05"}, - {file = "mypy-0.931-cp37-cp37m-win_amd64.whl", hash = "sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7"}, - {file = "mypy-0.931-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0"}, - {file = "mypy-0.931-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069"}, - {file = "mypy-0.931-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799"}, - {file = "mypy-0.931-cp38-cp38-win_amd64.whl", hash = "sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a"}, - {file = "mypy-0.931-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166"}, - {file = "mypy-0.931-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266"}, - {file = "mypy-0.931-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd"}, - {file = "mypy-0.931-cp39-cp39-win_amd64.whl", hash = "sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697"}, - {file = "mypy-0.931-py3-none-any.whl", hash = "sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d"}, - {file = "mypy-0.931.tar.gz", hash = "sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -passlib = [ - {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, - {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, -] -pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, -] -pbr = [ - {file = "pbr-5.8.1-py2.py3-none-any.whl", hash = "sha256:27108648368782d07bbf1cb468ad2e2eeef29086affd14087a6d04b7de8af4ec"}, - {file = "pbr-5.8.1.tar.gz", hash = "sha256:66bc5a34912f408bb3925bf21231cb6f59206267b7f63f3503ef865c1a292e25"}, -] -pep8-naming = [ - {file = "pep8-naming-0.11.1.tar.gz", hash = "sha256:a1dd47dd243adfe8a83616e27cf03164960b507530f155db94e10b36a6cd6724"}, - {file = "pep8_naming-0.11.1-py2.py3-none-any.whl", hash = "sha256:f43bfe3eea7e0d73e8b5d07d6407ab47f2476ccaeff6937c84275cd30b016738"}, -] -platformdirs = [ - {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"}, - {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -psycopg2-binary = [ - {file = "psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:e847774f8ffd5b398a75bc1c18fbb56564cda3d629fe68fd81971fece2d3c67e"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68641a34023d306be959101b345732360fc2ea4938982309b786f7be1b43a4a1"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3303f8807f342641851578ee7ed1f3efc9802d00a6f83c101d21c608cb864460"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:e3699852e22aa68c10de06524a3721ade969abf382da95884e6a10ff798f9281"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:526ea0378246d9b080148f2d6681229f4b5964543c170dd10bf4faaab6e0d27f"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b1c8068513f5b158cf7e29c43a77eb34b407db29aca749d3eb9293ee0d3103ca"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:15803fa813ea05bef089fa78835118b5434204f3a17cb9f1e5dbfd0b9deea5af"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:152f09f57417b831418304c7f30d727dc83a12761627bb826951692cc6491e57"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:404224e5fef3b193f892abdbf8961ce20e0b6642886cfe1fe1923f41aaa75c9d"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:1f6b813106a3abdf7b03640d36e24669234120c72e91d5cbaeb87c5f7c36c65b"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2d872e3c9d5d075a2e104540965a1cf898b52274a5923936e5bfddb58c59c7c2"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:10bb90fb4d523a2aa67773d4ff2b833ec00857f5912bafcfd5f5414e45280fb1"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a52ecab70af13e899f7847b3e074eeb16ebac5615665db33bce8a1009cf33"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29b3ca4ec9defec6d42bf5feb36bb5817ba3c0230dd83b4edf4bf02684cd0ae"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:12b11322ea00ad8db8c46f18b7dfc47ae215e4df55b46c67a94b4effbaec7094"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:53293533fcbb94c202b7c800a12c873cfe24599656b341f56e71dd2b557be063"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c381bda330ddf2fccbafab789d83ebc6c53db126e4383e73794c74eedce855ef"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d29409b625a143649d03d0fd7b57e4b92e0ecad9726ba682244b73be91d2fdb"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:183a517a3a63503f70f808b58bfbf962f23d73b6dccddae5aa56152ef2bcb232"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:15c4e4cfa45f5a60599d9cec5f46cd7b1b29d86a6390ec23e8eebaae84e64554"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:adf20d9a67e0b6393eac162eb81fb10bc9130a80540f4df7e7355c2dd4af9fba"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f9ffd643bc7349eeb664eba8864d9e01f057880f510e4681ba40a6532f93c71"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:def68d7c21984b0f8218e8a15d514f714d96904265164f75f8d3a70f9c295667"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dffc08ca91c9ac09008870c9eb77b00a46b3378719584059c034b8945e26b272"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:280b0bb5cbfe8039205c7981cceb006156a675362a00fe29b16fbc264e242834"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:af9813db73395fb1fc211bac696faea4ca9ef53f32dc0cfa27e4e7cf766dcf24"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:63638d875be8c2784cfc952c9ac34e2b50e43f9f0a0660b65e2a87d656b3116c"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ffb7a888a047696e7f8240d649b43fb3644f14f0ee229077e7f6b9f9081635bd"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c9d5450c566c80c396b7402895c4369a410cab5a82707b11aee1e624da7d004"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:d1c1b569ecafe3a69380a94e6ae09a4789bbb23666f3d3a08d06bbd2451f5ef1"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8fc53f9af09426a61db9ba357865c77f26076d48669f2e1bb24d85a22fb52307"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win32.whl", hash = "sha256:6472a178e291b59e7f16ab49ec8b4f3bdada0a879c68d3817ff0963e722a82ce"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35168209c9d51b145e459e05c31a9eaeffa9a6b0fd61689b48e07464ffd1a83e"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:47133f3f872faf28c1e87d4357220e809dfd3fa7c64295a4a148bcd1e6e34ec9"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91920527dea30175cc02a1099f331aa8c1ba39bf8b7762b7b56cbf54bc5cce42"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887dd9aac71765ac0d0bac1d0d4b4f2c99d5f5c1382d8b770404f0f3d0ce8a39"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:1f14c8b0942714eb3c74e1e71700cbbcb415acbc311c730370e70c578a44a25c"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7af0dd86ddb2f8af5da57a976d27cd2cd15510518d582b478fbb2292428710b4"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93cd1967a18aa0edd4b95b1dfd554cf15af657cb606280996d393dadc88c3c35"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bda845b664bb6c91446ca9609fc69f7db6c334ec5e4adc87571c34e4f47b7ddb"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:01310cf4cf26db9aea5158c217caa92d291f0500051a6469ac52166e1a16f5b7"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99485cab9ba0fa9b84f1f9e1fef106f44a46ef6afdeec8885e0b88d0772b49e8"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win32.whl", hash = "sha256:46f0e0a6b5fa5851bbd9ab1bc805eef362d3a230fbdfbc209f4a236d0a7a990d"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:accfe7e982411da3178ec690baaceaad3c278652998b2c45828aaac66cd8285f"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pycodestyle = [ - {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, - {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, -] -pycparser = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] -pydantic = [ - {file = "pydantic-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb23bcc093697cdea2708baae4f9ba0e972960a835af22560f6ae4e7e47d33f5"}, - {file = "pydantic-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1d5278bd9f0eee04a44c712982343103bba63507480bfd2fc2790fa70cd64cf4"}, - {file = "pydantic-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab624700dc145aa809e6f3ec93fb8e7d0f99d9023b713f6a953637429b437d37"}, - {file = "pydantic-1.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8d7da6f1c1049eefb718d43d99ad73100c958a5367d30b9321b092771e96c25"}, - {file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3c3b035103bd4e2e4a28da9da7ef2fa47b00ee4a9cf4f1a735214c1bcd05e0f6"}, - {file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3011b975c973819883842c5ab925a4e4298dffccf7782c55ec3580ed17dc464c"}, - {file = "pydantic-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:086254884d10d3ba16da0588604ffdc5aab3f7f09557b998373e885c690dd398"}, - {file = "pydantic-1.9.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0fe476769acaa7fcddd17cadd172b156b53546ec3614a4d880e5d29ea5fbce65"}, - {file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8e9dcf1ac499679aceedac7e7ca6d8641f0193c591a2d090282aaf8e9445a46"}, - {file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1e4c28f30e767fd07f2ddc6f74f41f034d1dd6bc526cd59e63a82fe8bb9ef4c"}, - {file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c86229333cabaaa8c51cf971496f10318c4734cf7b641f08af0a6fbf17ca3054"}, - {file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:c0727bda6e38144d464daec31dff936a82917f431d9c39c39c60a26567eae3ed"}, - {file = "pydantic-1.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:dee5ef83a76ac31ab0c78c10bd7d5437bfdb6358c95b91f1ba7ff7b76f9996a1"}, - {file = "pydantic-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9c9bdb3af48e242838f9f6e6127de9be7063aad17b32215ccc36a09c5cf1070"}, - {file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee7e3209db1e468341ef41fe263eb655f67f5c5a76c924044314e139a1103a2"}, - {file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b6037175234850ffd094ca77bf60fb54b08b5b22bc85865331dd3bda7a02fa1"}, - {file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b2571db88c636d862b35090ccf92bf24004393f85c8870a37f42d9f23d13e032"}, - {file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8b5ac0f1c83d31b324e57a273da59197c83d1bb18171e512908fe5dc7278a1d6"}, - {file = "pydantic-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bbbc94d0c94dd80b3340fc4f04fd4d701f4b038ebad72c39693c794fd3bc2d9d"}, - {file = "pydantic-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e0896200b6a40197405af18828da49f067c2fa1f821491bc8f5bde241ef3f7d7"}, - {file = "pydantic-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bdfdadb5994b44bd5579cfa7c9b0e1b0e540c952d56f627eb227851cda9db77"}, - {file = "pydantic-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:574936363cd4b9eed8acdd6b80d0143162f2eb654d96cb3a8ee91d3e64bf4cf9"}, - {file = "pydantic-1.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c556695b699f648c58373b542534308922c46a1cda06ea47bc9ca45ef5b39ae6"}, - {file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f947352c3434e8b937e3aa8f96f47bdfe6d92779e44bb3f41e4c213ba6a32145"}, - {file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5e48ef4a8b8c066c4a31409d91d7ca372a774d0212da2787c0d32f8045b1e034"}, - {file = "pydantic-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:96f240bce182ca7fe045c76bcebfa0b0534a1bf402ed05914a6f1dadff91877f"}, - {file = "pydantic-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:815ddebb2792efd4bba5488bc8fde09c29e8ca3227d27cf1c6990fc830fd292b"}, - {file = "pydantic-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c5b77947b9e85a54848343928b597b4f74fc364b70926b3c4441ff52620640c"}, - {file = "pydantic-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c68c3bc88dbda2a6805e9a142ce84782d3930f8fdd9655430d8576315ad97ce"}, - {file = "pydantic-1.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a79330f8571faf71bf93667d3ee054609816f10a259a109a0738dac983b23c3"}, - {file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f5a64b64ddf4c99fe201ac2724daada8595ada0d102ab96d019c1555c2d6441d"}, - {file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a733965f1a2b4090a5238d40d983dcd78f3ecea221c7af1497b845a9709c1721"}, - {file = "pydantic-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cc6a4cb8a118ffec2ca5fcb47afbacb4f16d0ab8b7350ddea5e8ef7bcc53a16"}, - {file = "pydantic-1.9.0-py3-none-any.whl", hash = "sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3"}, - {file = "pydantic-1.9.0.tar.gz", hash = "sha256:742645059757a56ecd886faf4ed2441b9c0cd406079c2b4bee51bcc3fbcd510a"}, -] -pydocstyle = [ - {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, - {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, -] -pyflakes = [ - {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, - {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, -] -pygments = [ - {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, - {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, -] -pyjwt = [ - {file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"}, - {file = "PyJWT-2.3.0.tar.gz", hash = "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41"}, -] -pyparsing = [ - {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, - {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, -] -pypika = [ - {file = "pypika-0.48.8.tar.gz", hash = "sha256:45af481d8523d60f87e308dee6ff5c454f331c8ce3a675e5398fbea6c20fe1b1"}, -] -pytest = [ - {file = "pytest-7.0.0-py3-none-any.whl", hash = "sha256:42901e6bd4bd4a0e533358a86e848427a49005a3256f657c5c8f8dd35ef137a9"}, - {file = "pytest-7.0.0.tar.gz", hash = "sha256:dad48ffda394e5ad9aa3b7d7ddf339ed502e5e365b1350e0af65f4a602344b11"}, -] -pytest-asyncio = [ - {file = "pytest-asyncio-0.18.0.tar.gz", hash = "sha256:5c510e5d3ad0f97bab0ae0223363d2aa6329bbbafb0981d96dbed6a804a99349"}, - {file = "pytest_asyncio-0.18.0-py3-none-any.whl", hash = "sha256:5e33f5010402309ff4e8cdec04e76b057ae73e0c132f12c6aa2fa6ec8cabfbf1"}, -] -pytest-cov = [ - {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, - {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, -] -pytest-env = [ - {file = "pytest-env-0.6.2.tar.gz", hash = "sha256:7e94956aef7f2764f3c147d216ce066bf6c42948bb9e293169b1b1c880a580c2"}, -] -pytest-forked = [ - {file = "pytest-forked-1.4.0.tar.gz", hash = "sha256:8b67587c8f98cbbadfdd804539ed5455b6ed03802203485dd2f53c1422d7440e"}, - {file = "pytest_forked-1.4.0-py3-none-any.whl", hash = "sha256:bbbb6717efc886b9d64537b41fb1497cfaf3c9601276be8da2cccfea5a3c8ad8"}, -] -pytest-xdist = [ - {file = "pytest-xdist-2.5.0.tar.gz", hash = "sha256:4580deca3ff04ddb2ac53eba39d76cb5dd5edeac050cb6fbc768b0dd712b4edf"}, - {file = "pytest_xdist-2.5.0-py3-none-any.whl", hash = "sha256:6fe5c74fec98906deb8f2d2b616b5c782022744978e7bd4695d39c8f42d0ce65"}, -] -python-dotenv = [ - {file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"}, - {file = "python_dotenv-0.19.2-py2.py3-none-any.whl", hash = "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3"}, -] -python-slugify = [ - {file = "python-slugify-5.0.2.tar.gz", hash = "sha256:f13383a0b9fcbe649a1892b9c8eb4f8eab1d6d84b84bb7a624317afa98159cab"}, - {file = "python_slugify-5.0.2-py2.py3-none-any.whl", hash = "sha256:6d8c5df75cd4a7c3a2d21e257633de53f52ab0265cd2d1dc62a730e8194a7380"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -requests = [ - {file = "requests-2.28.0-py3-none-any.whl", hash = "sha256:bc7861137fbce630f17b03d3ad02ad0bf978c844f3536d0edda6499dafce2b6f"}, - {file = "requests-2.28.0.tar.gz", hash = "sha256:d568723a7ebd25875d8d1eaf5dfa068cd2fc8194b2e483d7b1f7c81918dbec6b"}, -] -restructuredtext-lint = [ - {file = "restructuredtext_lint-1.3.2.tar.gz", hash = "sha256:d3b10a1fe2ecac537e51ae6d151b223b78de9fafdd50e5eb6b08c243df173c80"}, -] -rfc3986 = [ - {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, - {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -smmap = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, -] -sniffio = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, -] -snowballstemmer = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] -sqlalchemy = [ - {file = "SQLAlchemy-1.4.31-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c3abc34fed19fdeaead0ced8cf56dd121f08198008c033596aa6aae7cc58f59f"}, - {file = "SQLAlchemy-1.4.31-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8d0949b11681380b4a50ac3cd075e4816afe9fa4a8c8ae006c1ca26f0fa40ad8"}, - {file = "SQLAlchemy-1.4.31-cp27-cp27m-win32.whl", hash = "sha256:f3b7ec97e68b68cb1f9ddb82eda17b418f19a034fa8380a0ac04e8fe01532875"}, - {file = "SQLAlchemy-1.4.31-cp27-cp27m-win_amd64.whl", hash = "sha256:81f2dd355b57770fdf292b54f3e0a9823ec27a543f947fa2eb4ec0df44f35f0d"}, - {file = "SQLAlchemy-1.4.31-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4ad31cec8b49fd718470328ad9711f4dc703507d434fd45461096da0a7135ee0"}, - {file = "SQLAlchemy-1.4.31-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:05fa14f279d43df68964ad066f653193187909950aa0163320b728edfc400167"}, - {file = "SQLAlchemy-1.4.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dccff41478050e823271642837b904d5f9bda3f5cf7d371ce163f00a694118d6"}, - {file = "SQLAlchemy-1.4.31-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57205844f246bab9b666a32f59b046add8995c665d9ecb2b7b837b087df90639"}, - {file = "SQLAlchemy-1.4.31-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea8210090a816d48a4291a47462bac750e3bc5c2442e6d64f7b8137a7c3f9ac5"}, - {file = "SQLAlchemy-1.4.31-cp310-cp310-win32.whl", hash = "sha256:2e216c13ecc7fcdcbb86bb3225425b3ed338e43a8810c7089ddb472676124b9b"}, - {file = "SQLAlchemy-1.4.31-cp310-cp310-win_amd64.whl", hash = "sha256:e3a86b59b6227ef72ffc10d4b23f0fe994bef64d4667eab4fb8cd43de4223bec"}, - {file = "SQLAlchemy-1.4.31-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:2fd4d3ca64c41dae31228b80556ab55b6489275fb204827f6560b65f95692cf3"}, - {file = "SQLAlchemy-1.4.31-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f22c040d196f841168b1456e77c30a18a3dc16b336ddbc5a24ce01ab4e95ae0"}, - {file = "SQLAlchemy-1.4.31-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c0c7171aa5a57e522a04a31b84798b6c926234cb559c0939840c3235cf068813"}, - {file = "SQLAlchemy-1.4.31-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d046a9aeba9bc53e88a41e58beb72b6205abb9a20f6c136161adf9128e589db5"}, - {file = "SQLAlchemy-1.4.31-cp36-cp36m-win32.whl", hash = "sha256:d86132922531f0dc5a4f424c7580a472a924dd737602638e704841c9cb24aea2"}, - {file = "SQLAlchemy-1.4.31-cp36-cp36m-win_amd64.whl", hash = "sha256:ca68c52e3cae491ace2bf39b35fef4ce26c192fd70b4cd90f040d419f70893b5"}, - {file = "SQLAlchemy-1.4.31-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:cf2cd387409b12d0a8b801610d6336ee7d24043b6dd965950eaec09b73e7262f"}, - {file = "SQLAlchemy-1.4.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb4b15fb1f0aafa65cbdc62d3c2078bea1ceecbfccc9a1f23a2113c9ac1191fa"}, - {file = "SQLAlchemy-1.4.31-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c317ddd7c586af350a6aef22b891e84b16bff1a27886ed5b30f15c1ed59caeaa"}, - {file = "SQLAlchemy-1.4.31-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c7ed6c69debaf6198fadb1c16ae1253a29a7670bbf0646f92582eb465a0b999"}, - {file = "SQLAlchemy-1.4.31-cp37-cp37m-win32.whl", hash = "sha256:6a01ec49ca54ce03bc14e10de55dfc64187a2194b3b0e5ac0fdbe9b24767e79e"}, - {file = "SQLAlchemy-1.4.31-cp37-cp37m-win_amd64.whl", hash = "sha256:330eb45395874cc7787214fdd4489e2afb931bc49e0a7a8f9cd56d6e9c5b1639"}, - {file = "SQLAlchemy-1.4.31-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5e9c7b3567edbc2183607f7d9f3e7e89355b8f8984eec4d2cd1e1513c8f7b43f"}, - {file = "SQLAlchemy-1.4.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de85c26a5a1c72e695ab0454e92f60213b4459b8d7c502e0be7a6369690eeb1a"}, - {file = "SQLAlchemy-1.4.31-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:975f5c0793892c634c4920057da0de3a48bbbbd0a5c86f5fcf2f2fedf41b76da"}, - {file = "SQLAlchemy-1.4.31-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5c20c8415173b119762b6110af64448adccd4d11f273fb9f718a9865b88a99c"}, - {file = "SQLAlchemy-1.4.31-cp38-cp38-win32.whl", hash = "sha256:b35dca159c1c9fa8a5f9005e42133eed82705bf8e243da371a5e5826440e65ca"}, - {file = "SQLAlchemy-1.4.31-cp38-cp38-win_amd64.whl", hash = "sha256:b7b20c88873675903d6438d8b33fba027997193e274b9367421e610d9da76c08"}, - {file = "SQLAlchemy-1.4.31-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:85e4c244e1de056d48dae466e9baf9437980c19fcde493e0db1a0a986e6d75b4"}, - {file = "SQLAlchemy-1.4.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79e73d5ee24196d3057340e356e6254af4d10e1fc22d3207ea8342fc5ffb977"}, - {file = "SQLAlchemy-1.4.31-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:15a03261aa1e68f208e71ae3cd845b00063d242cbf8c87348a0c2c0fc6e1f2ac"}, - {file = "SQLAlchemy-1.4.31-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ddc5e5ccc0160e7ad190e5c61eb57560f38559e22586955f205e537cda26034"}, - {file = "SQLAlchemy-1.4.31-cp39-cp39-win32.whl", hash = "sha256:289465162b1fa1e7a982f8abe59d26a8331211cad4942e8031d2b7db1f75e649"}, - {file = "SQLAlchemy-1.4.31-cp39-cp39-win_amd64.whl", hash = "sha256:9e4fb2895b83993831ba2401b6404de953fdbfa9d7d4fa6a4756294a83bbc94f"}, - {file = "SQLAlchemy-1.4.31.tar.gz", hash = "sha256:582b59d1e5780a447aada22b461e50b404a9dc05768da1d87368ad8190468418"}, -] -starlette = [ - {file = "starlette-0.17.1-py3-none-any.whl", hash = "sha256:26a18cbda5e6b651c964c12c88b36d9898481cd428ed6e063f5f29c418f73050"}, - {file = "starlette-0.17.1.tar.gz", hash = "sha256:57eab3cc975a28af62f6faec94d355a410634940f10b30d68d31cb5ec1b44ae8"}, -] -stevedore = [ - {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"}, - {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"}, -] -testfixtures = [ - {file = "testfixtures-6.18.3-py2.py3-none-any.whl", hash = "sha256:6ddb7f56a123e1a9339f130a200359092bd0a6455e31838d6c477e8729bb7763"}, - {file = "testfixtures-6.18.3.tar.gz", hash = "sha256:2600100ae96ffd082334b378e355550fef8b4a529a6fa4c34f47130905c7426d"}, -] -text-unidecode = [ - {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, - {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, -] -tomli = [ - {file = "tomli-2.0.0-py3-none-any.whl", hash = "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224"}, - {file = "tomli-2.0.0.tar.gz", hash = "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"}, -] -typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, -] -unidecode = [ - {file = "Unidecode-1.3.2-py3-none-any.whl", hash = "sha256:215fe33c9d1c889fa823ccb66df91b02524eb8cc8c9c80f9c5b8129754d27829"}, - {file = "Unidecode-1.3.2.tar.gz", hash = "sha256:669898c1528912bcf07f9819dc60df18d057f7528271e31f8ec28cc88ef27504"}, -] -urllib3 = [ - {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, - {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, -] -uvicorn = [ - {file = "uvicorn-0.17.4-py3-none-any.whl", hash = "sha256:e85872d84fb651cccc4c5d2a71cf7ead055b8fb4d8f1e78e36092282c0cf2aec"}, - {file = "uvicorn-0.17.4.tar.gz", hash = "sha256:25850bbc86195a71a6477b3e4b3b7b4c861fb687fb96912972ce5324472b1011"}, -] -wemake-python-styleguide = [ - {file = "wemake-python-styleguide-0.16.0.tar.gz", hash = "sha256:3bf0a4962404e6fd6fa479e72e2ba3fb75d5920ea6c44b72b45240c9e519543c"}, - {file = "wemake_python_styleguide-0.16.0-py3-none-any.whl", hash = "sha256:8caa92b4aa77b08a505d718553238812d1b612b1036bc171ca3aa18345efe0b4"}, -] -win32-setctime = [ - {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, - {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, -] diff --git a/.framework/python/backend/pyproject.toml b/.framework/python/backend/pyproject.toml deleted file mode 100644 index b974ae6..0000000 --- a/.framework/python/backend/pyproject.toml +++ /dev/null @@ -1,72 +0,0 @@ -[tool.poetry] -name = "Anythink Market Backend" -version = "0.0.0" -description = "Backend logic implementation for Anythink Market" -authors=["Anythink"] -license = "MIT" - -[tool.poetry.dependencies] -python = "3.9.13" -uvicorn = "^0.17.4" -fastapi = "^0.73.0" -pydantic = { version = "^1.8", extras = ["email", "dotenv"] } -passlib = { version = "^1.7", extras = ["bcrypt"] } -pyjwt = "^2.3" -databases = "^0.5.5" -asyncpg = "^0.25.0" -psycopg2-binary = "^2.9.3" -aiosql = "^3.3.1" -pypika = "^0.48.8" -alembic = "^1.7" -python-slugify = "^5.0" -Unidecode = "^1.3" -loguru = "^0.6.0" -requests = "^2.28.0" -gunicorn = "^20.1.0" - -[tool.poetry.dev-dependencies] -black = "^22.1.0" -isort = "^5.10" -autoflake = "^1.4" -wemake-python-styleguide = "^0.16.0" -mypy = "^0.931" -flake8-fixme = "^1.1" -pytest = "^7.0" -pytest-cov = "^3.0" -pytest-asyncio = "^0.18.0" -pytest-env = "^0.6.2" -pytest-xdist = "^2.4.0" -httpx = "^0.22.0" -asgi-lifespan = "^1.0.1" - -[tool.isort] -profile = "black" -src_paths = ["app", "tests"] -combine_as_imports = true - -[tool.pytest.ini_options] -testpaths = "tests" -filterwarnings = "error" -addopts = ''' - --strict-markers - --tb=short - --cov=app - --cov=tests - --cov-branch - --cov-report=term-missing - --cov-report=html - --cov-report=xml - --no-cov-on-fail - --cov-fail-under=100 - --numprocesses=auto - --asyncio-mode=auto -''' -env = [ - "SECRET_KEY=secret", - "MAX_CONNECTIONS_COUNT=1", - "MIN_CONNECTIONS_COUNT=1" -] - -[build-system] -requires = ["poetry>=1.0"] -build-backend = "poetry.masonry.api" diff --git a/.framework/python/backend/requirements.txt b/.framework/python/backend/requirements.txt deleted file mode 100644 index 4731c9d..0000000 --- a/.framework/python/backend/requirements.txt +++ /dev/null @@ -1,43 +0,0 @@ -aiosql==3.3.1 -alembic==1.7.6 -anyio==3.5.0 -asgiref==3.5.0 -asyncpg==0.25.0 -bcrypt==3.2.0 -certifi==2021.10.8 -cffi==1.15.0 -charset-normalizer==2.0.11 -click==8.0.3 -colorama==0.4.4; platform_system == "Windows" -colorama==0.4.4; sys_platform == "win32" -contextlib2==21.6.0 -databases==0.5.5 -dnspython==2.2.0 -email-validator==1.1.3 -fastapi==0.73.0 -greenlet==1.1.2; python_version >= "3" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") -gunicorn==20.1.0 -h11==0.12.0 -idna==3.3 -loguru==0.6.0 -mako==1.1.6 -markupsafe==2.0.1 -passlib==1.7.4 -psycopg2-binary==2.9.3 -pycparser==2.21 -pydantic==1.9.0 -pyjwt==2.3.0 -pypika==0.48.8 -python-dotenv==0.19.2 -python-slugify==5.0.2 -requests==2.28.0 -six==1.16.0 -sniffio==1.2.0 -sqlalchemy==1.4.31 -starlette==0.17.1 -text-unidecode==1.3 -typing-extensions==3.10.0.2 -unidecode==1.3.2 -urllib3==1.26.9 -uvicorn==0.17.4 -win32-setctime==1.1.0; sys_platform == "win32" diff --git a/.framework/python/backend/runtime.txt b/.framework/python/backend/runtime.txt deleted file mode 100644 index c6f7782..0000000 --- a/.framework/python/backend/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.9.13 diff --git a/.framework/python/backend/scripts/format b/.framework/python/backend/scripts/format deleted file mode 100755 index 64a9b14..0000000 --- a/.framework/python/backend/scripts/format +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -e - -isort --force-single-line-imports app tests -autoflake --recursive --remove-all-unused-imports --remove-unused-variables --in-place app tests -black app tests -isort app tests diff --git a/.framework/python/backend/scripts/heroku_release.sh b/.framework/python/backend/scripts/heroku_release.sh deleted file mode 100755 index 95d8fe5..0000000 --- a/.framework/python/backend/scripts/heroku_release.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# -# Usage: bin/heroku_deploy - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[0;33m' -NO_COLOR='\033[0m' - -set -euo pipefail - -printf "\n⏳${YELLOW} [Release Phase]: Running schema migrations.${NO_COLOR}\n" -alembic upgrade head -printf "\n⏳${YELLOW} [Release Phase]: Seeding.${NO_COLOR}\n" -./seeds.sh -printf "\n🎉${GREEN} [Release Phase]: Database is up to date.${NO_COLOR}\n" diff --git a/.framework/python/backend/scripts/lint b/.framework/python/backend/scripts/lint deleted file mode 100755 index ea56cfe..0000000 --- a/.framework/python/backend/scripts/lint +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - - -flake8 app --exclude=app/db/migrations -mypy app - -black --check app --diff -isort --check-only app diff --git a/.framework/python/backend/scripts/test b/.framework/python/backend/scripts/test deleted file mode 100755 index 23f48d1..0000000 --- a/.framework/python/backend/scripts/test +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -pytest --cov=app --cov=tests --cov-report=term-missing --cov-config=setup.cfg ${@} diff --git a/.framework/python/backend/scripts/test-cov-html b/.framework/python/backend/scripts/test-cov-html deleted file mode 100755 index de5f3b1..0000000 --- a/.framework/python/backend/scripts/test-cov-html +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -bash scripts/test --cov-report=html ${@} diff --git a/.framework/python/backend/seeds.sh b/.framework/python/backend/seeds.sh deleted file mode 100755 index eab281e..0000000 --- a/.framework/python/backend/seeds.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -python3 ./app/db/seeds.py diff --git a/.framework/python/backend/setup.cfg b/.framework/python/backend/setup.cfg deleted file mode 100644 index c880ac5..0000000 --- a/.framework/python/backend/setup.cfg +++ /dev/null @@ -1,88 +0,0 @@ -[coverage:report] -precision = 2 -exclude_lines = - pragma: no cover - raise NotImplementedError - raise NotImplemented - -[coverage:run] -source = app -branch = True - -[mypy] -plugins = pydantic.mypy - -strict_optional = True -warn_redundant_casts = True -warn_unused_ignores = True -disallow_any_generics = True -check_untyped_defs = True - -disallow_untyped_defs = True - -[pydantic-mypy] -init_forbid_extra = True -init_typed = True -warn_required_dynamic_aliases = True -warn_untyped_fields = True - -[mypy-sqlalchemy.*] -ignore_missing_imports = True - -[mypy-alembic.*] -ignore_missing_imports = True - -[mypy-loguru.*] -ignore_missing_imports = True - -[mypy-asyncpg.*] -ignore_missing_imports = True - -[mypy-bcrypt.*] -ignore_missing_imports = True - -[mypy-passlib.*] -ignore_missing_imports = True - -[mypy-slugify.*] -ignore_missing_imports = True - -[mypy-pypika.*] -ignore_missing_imports = True - -[flake8] -format = wemake -max-line-length = 88 -per-file-ignores = - # ignore error on builtin names for TypedTable classes, since just mapper for SQL table - app/db/queries/tables.py: WPS125, - - # ignore black disabling in some places for queries building using pypika - app/db/repositories/*.py: E800, - - app/api/dependencies/authentication.py: WPS201, -ignore = - # common errors: - # FastAPI architecture requires a lot of functions calls as default arguments, so ignore it here. - B008, - # docs are missing in this project. - D, RST - - # WPS: 3xx - # IMO, but the obligation to specify the base class is redundant. - WPS306, - - # WPS: 4xx - # FastAPI architecture requires a lot of complex calls as default arguments, so ignore it here. - WPS404, - # again, FastAPI DI architecture involves a lot of nested functions as DI providers. - WPS430, - # used for pypika operations - WPS465, - - # WPS: 6xx - # pydantic defines models in dataclasses model style, but not supported by WPS. - WPS601, -no-accept-encodings = True -nested-classes-whitelist=Config -inline-quotes = double diff --git a/.framework/python/charts/.helmignore b/.framework/python/charts/.helmignore deleted file mode 100644 index 0e8a0eb..0000000 --- a/.framework/python/charts/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/.framework/python/charts/Chart.yaml b/.framework/python/charts/Chart.yaml deleted file mode 100644 index b2beb19..0000000 --- a/.framework/python/charts/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: app -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" diff --git a/.framework/python/charts/templates/_helpers.yml b/.framework/python/charts/templates/_helpers.yml deleted file mode 100644 index 49515f2..0000000 --- a/.framework/python/charts/templates/_helpers.yml +++ /dev/null @@ -1,24 +0,0 @@ -{{- define "anythink-tenant.backendHost" -}} - https://{{- .Release.Namespace }}-api. - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.stagingBackendHost }} - {{- else }} - {{- .Values.productionBackendHost }} - {{- end }} -{{- end }} - -{{- define "anythink-tenant.backendRepository" -}} - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.backend.image.stagingRepository }} - {{- else }} - {{- .Values.backend.image.repository }} - {{- end }} -{{- end }} - -{{- define "anythink-tenant.frontendRepository" -}} - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.frontend.image.stagingRepository }} - {{- else }} - {{- .Values.frontend.image.repository }} - {{- end }} -{{- end }} diff --git a/.framework/python/charts/templates/anythink-backend-deployment.yaml b/.framework/python/charts/templates/anythink-backend-deployment.yaml deleted file mode 100644 index 3997ff5..0000000 --- a/.framework/python/charts/templates/anythink-backend-deployment.yaml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.backend.serviceName }} - name: {{ .Values.backend.serviceName }} -spec: - replicas: {{ .Values.backend.replicaCount }} - selector: - matchLabels: - app: {{ .Values.backend.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.backend.serviceName }} - date: {{ now | unixEpoch | quote }} - spec: - containers: - - args: - - sh - - -c - - "poetry run uvicorn --host=0.0.0.0 --port={{ .Values.backend.containerPort }} app.main:app" - env: - - name: APP_ENV - value: dev - - name: SECRET_KEY - value: secret - - name: DEBUG - value: "True" - - name: DATABASE_URL - value: "{{ .Values.database.connectionProtocol }}{{ .Values.database.env.password }}:@{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}/{{ .Values.database.databaseName }}" - image: "{{ include "anythink-tenant.backendRepository" .}}:{{ .Values.backend.image.tag }}" - imagePullPolicy: {{ .Values.backend.image.pullPolicy }} - name: {{ .Values.backend.serviceName }} - ports: - - containerPort: {{ .Values.backend.containerPort }} - name: http - protocol: TCP - startupProbe: - httpGet: - path: /health - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: /health - port: http - readinessProbe: - httpGet: - path: /health - port: http - resources: - {{- toYaml .Values.backend.resources | nindent 12 }} - initContainers: - - command: - - sh - - -c - - "poetry run alembic upgrade head && ./seeds.sh" - env: - - name: APP_ENV - value: dev - - name: SECRET_KEY - value: secret - - name: DEBUG - value: "True" - - name: DATABASE_URL - value: "{{ .Values.database.connectionProtocol}}{{ .Values.database.env.password}}:@{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}/{{ .Values.database.databaseName }}" - image: "{{ include "anythink-tenant.backendRepository" .}}:{{ .Values.backend.image.tag }}" - imagePullPolicy: {{ .Values.backend.image.pullPolicy }} - name: db-migrations - restartPolicy: Always diff --git a/.framework/python/charts/templates/anythink-backend-service.yaml b/.framework/python/charts/templates/anythink-backend-service.yaml deleted file mode 100644 index 21bb516..0000000 --- a/.framework/python/charts/templates/anythink-backend-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: {{ .Values.backend.serviceName }} - name: {{ .Values.backend.serviceName }} -spec: - ports: - - name: "{{ .Values.backend.containerPort }}" - port: {{ .Values.backend.containerPort }} - targetPort: {{ .Values.backend.containerPort }} - selector: - app: {{ .Values.backend.serviceName }} diff --git a/.framework/python/charts/templates/anythink-frontend-deployment.yaml b/.framework/python/charts/templates/anythink-frontend-deployment.yaml deleted file mode 100644 index f9be249..0000000 --- a/.framework/python/charts/templates/anythink-frontend-deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.frontend.serviceName }} - name: {{ .Values.frontend.serviceName }} -spec: - replicas: {{ .Values.frontend.replicaCount }} - selector: - matchLabels: - app: {{ .Values.frontend.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.frontend.serviceName }} - date: {{ now | unixEpoch | quote }} - spec: - containers: - - args: - - sh - - -c - - yarn start - env: - - name: NODE_ENV - value: development - - name: PORT - value: "{{ .Values.frontend.containerPort }}" - - name: REACT_APP_BACKEND_URL - value: {{ include "anythink-tenant.backendHost" .}} - image: "{{ include "anythink-tenant.frontendRepository" .}}:{{ .Values.frontend.image.tag }}" - imagePullPolicy: {{ .Values.frontend.image.pullPolicy }} - name: {{ .Values.frontend.serviceName }} - ports: - - containerPort: {{ .Values.frontend.containerPort }} - name: http - protocol: TCP - startupProbe: - httpGet: - path: / - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: / - port: http - readinessProbe: - httpGet: - path: / - port: http - resources: - {{- toYaml .Values.frontend.resources | nindent 12 }} - restartPolicy: Always diff --git a/.framework/python/charts/templates/anythink-frontend-service.yaml b/.framework/python/charts/templates/anythink-frontend-service.yaml deleted file mode 100644 index 217f8c5..0000000 --- a/.framework/python/charts/templates/anythink-frontend-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: {{ .Values.frontend.serviceName }} - name: {{ .Values.frontend.serviceName }} -spec: - ports: - - name: "{{ .Values.frontend.containerPort }}" - port: {{ .Values.frontend.containerPort }} - targetPort: {{ .Values.frontend.containerPort }} - selector: - app: {{ .Values.frontend.serviceName }} diff --git a/.framework/python/charts/templates/database-deployment.yaml b/.framework/python/charts/templates/database-deployment.yaml deleted file mode 100644 index 19752ee..0000000 --- a/.framework/python/charts/templates/database-deployment.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if .Values.database.deploy }} -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.database.serviceName }} - name: {{ .Values.database.serviceName }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.database.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.database.serviceName }} - spec: - containers: - - image: "{{ .Values.database.image.repository }}:{{ .Values.database.image.tag }}" - name: {{ .Values.database.serviceName }} - env: - - name: POSTGRES_HOST_AUTH_METHOD - value: trust - - name: POSTGRES_USER - value: {{ .Values.database.env.userName }} - - name: POSTGRES_PASSWORD - value: {{ .Values.database.env.password }} - - name: POSTGRES_DB - value: {{ .Values.database.databaseName }} - imagePullPolicy: {{ .Values.database.image.pullPolicy }} - ports: - - containerPort: {{ .Values.database.containerPort }} - resources: {} - volumeMounts: - - mountPath: /data/db - name: {{ .Values.database.serviceName }}-0 - restartPolicy: Always - volumes: - - name: {{ .Values.database.serviceName }}-0 - persistentVolumeClaim: - claimName: {{ .Values.database.serviceName }}-0 -{{- end }} diff --git a/.framework/python/charts/templates/database-pvc.yaml b/.framework/python/charts/templates/database-pvc.yaml deleted file mode 100644 index 88517f3..0000000 --- a/.framework/python/charts/templates/database-pvc.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app: {{ .Values.database.serviceName }}-0 - name: {{ .Values.database.serviceName }}-0 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Mi diff --git a/.framework/python/charts/templates/database-service.yaml b/.framework/python/charts/templates/database-service.yaml deleted file mode 100644 index 80b47d3..0000000 --- a/.framework/python/charts/templates/database-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: {{ .Values.database.serviceName }} - name: {{ .Values.database.serviceName }} -spec: - ports: - - name: "{{ .Values.database.servicePort }}" - port: {{ .Values.database.servicePort }} - targetPort: {{ .Values.database.servicePort }} - selector: - app: {{ .Values.database.serviceName }} diff --git a/.framework/python/charts/values.yaml b/.framework/python/charts/values.yaml deleted file mode 100644 index 0464a04..0000000 --- a/.framework/python/charts/values.yaml +++ /dev/null @@ -1,70 +0,0 @@ -clusterEnv: "" -productionBackendHost: "prod.anythink.market" -stagingBackendHost: "staging.anythink.market" - -backend: - serviceName: anythink-backend - containerPort: 3000 - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/anythink-backend - stagingRepository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/staging-anythink-backend - pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 128Mi - -frontend: - serviceName: anythink-frontend - containerPort: 3001 - replicaCount: 1 - service: - type: ClusterIP - port: 80 - image: - repository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/anythink-frontend - stagingRepository: 498915426792.dkr.ecr.us-east-2.amazonaws.com/staging-anythink-frontend - pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - resources: - limits: - cpu: 600m - memory: 768Mi - requests: - cpu: 100m - memory: 128Mi - -database: - deploy: true - connectionProtocol: postgresql:// - serviceName: postgres-python - containerPort: 5433 - servicePort: 5432 - databaseName: anythink-market - replicaCount: 1 - env: - password: postgres - service: - type: ClusterIP - port: 80 - image: - repository: postgres - pullPolicy: IfNotPresent - tag: "latest" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi diff --git a/.framework/python/docker-compose.yml b/.framework/python/docker-compose.yml deleted file mode 100644 index 65aaee9..0000000 --- a/.framework/python/docker-compose.yml +++ /dev/null @@ -1,67 +0,0 @@ -version: "3.8" -services: - anythink-backend-python: - build: ./backend - container_name: anythink-backend-python - command: > - sh -c "cd backend && - poetry install && - poetry export -f "requirements.txt" --without-hashes --with-credentials > "requirements.txt" - /wait-for-it.sh postgres-python:5432 -q -t 60 && - poetry run alembic upgrade head && - poetry run gunicorn app.main:app --worker-class=uvicorn.workers.UvicornWorker --bind=0.0.0.0:3000 --workers=5" - working_dir: /usr/src - volumes: - - ./:/usr/src - ports: - - "3000:3000" - environment: - - APP_ENV=dev - - SECRET_KEY=secret - - DEBUG=True - - DATABASE_URL=postgresql://postgres:@postgres-python:5432/anythink-market - - GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN=${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN} - depends_on: - - "postgres-python" - - anythink-frontend-react: - build: ./frontend - container_name: anythink-frontend-react - command: sh -c "cd frontend && yarn install && /wait-for-it.sh anythink-backend-python:3000 -t 120 --strict -- curl --head -X GET --retry 30 --retry-connrefused --retry-delay 1 anythink-backend-python:3000/api/ping && yarn start" - environment: - - NODE_ENV=development - - PORT=3001 - - REACT_APP_BACKEND_URL=${CODESPACE_BACKEND_URL:-http://localhost:3000} - - WDS_SOCKET_PORT=${CODESPACE_WDS_SOCKET_PORT:-3001} - working_dir: /usr/src - volumes: - - ./:/usr/src/ - - /usr/src/frontend/node_modules - ports: - - "3001:3001" - depends_on: - - "anythink-backend-python" - - postgres-python: - container_name: postgres-python - restart: on-failure - image: postgres - logging: - driver: none - environment: - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PASSWORD: postgres - POSTGRES_DB: anythink-market - volumes: - - ~/postgres/data:/data/db - ports: - - '5433:5432' - - anythink-ack: - image: public.ecr.aws/v0a2l7y2/wilco/anythink-ack:latest - container_name: anythink-ack - environment: - - GITHUB_TOKEN=$GITHUB_TOKEN - - CODESPACE_NAME=$CODESPACE_NAME - depends_on: - - "anythink-frontend-react" diff --git a/.framework/rails/.devcontainer/devcontainer.json b/.framework/rails/.devcontainer/devcontainer.json deleted file mode 100644 index 171e2d2..0000000 --- a/.framework/rails/.devcontainer/devcontainer.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Anythink Development Container", - "image": "public.ecr.aws/v0a2l7y2/wilco/anythink-devcontainer:latest" -} diff --git a/.framework/rails/backend/vendor/.keep b/.framework/rails/backend/vendor/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/charts/.helmignore b/.framework/rails/charts/.helmignore deleted file mode 100644 index 0e8a0eb..0000000 --- a/.framework/rails/charts/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/.framework/rails/charts/Chart.yaml b/.framework/rails/charts/Chart.yaml deleted file mode 100644 index b2beb19..0000000 --- a/.framework/rails/charts/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: app -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" diff --git a/.framework/rails/charts/templates/_helpers.yml b/.framework/rails/charts/templates/_helpers.yml deleted file mode 100644 index 49515f2..0000000 --- a/.framework/rails/charts/templates/_helpers.yml +++ /dev/null @@ -1,24 +0,0 @@ -{{- define "anythink-tenant.backendHost" -}} - https://{{- .Release.Namespace }}-api. - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.stagingBackendHost }} - {{- else }} - {{- .Values.productionBackendHost }} - {{- end }} -{{- end }} - -{{- define "anythink-tenant.backendRepository" -}} - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.backend.image.stagingRepository }} - {{- else }} - {{- .Values.backend.image.repository }} - {{- end }} -{{- end }} - -{{- define "anythink-tenant.frontendRepository" -}} - {{- if eq .Values.clusterEnv "staging" }} - {{- .Values.frontend.image.stagingRepository }} - {{- else }} - {{- .Values.frontend.image.repository }} - {{- end }} -{{- end }} diff --git a/.framework/rails/charts/templates/anythink-backend-service.yaml b/.framework/rails/charts/templates/anythink-backend-service.yaml deleted file mode 100644 index 21bb516..0000000 --- a/.framework/rails/charts/templates/anythink-backend-service.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - creationTimestamp: null - labels: - app: {{ .Values.backend.serviceName }} - name: {{ .Values.backend.serviceName }} -spec: - ports: - - name: "{{ .Values.backend.containerPort }}" - port: {{ .Values.backend.containerPort }} - targetPort: {{ .Values.backend.containerPort }} - selector: - app: {{ .Values.backend.serviceName }} diff --git a/.framework/rails/charts/templates/anythink-frontend-deployment.yaml b/.framework/rails/charts/templates/anythink-frontend-deployment.yaml deleted file mode 100644 index f9be249..0000000 --- a/.framework/rails/charts/templates/anythink-frontend-deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: {{ .Values.frontend.serviceName }} - name: {{ .Values.frontend.serviceName }} -spec: - replicas: {{ .Values.frontend.replicaCount }} - selector: - matchLabels: - app: {{ .Values.frontend.serviceName }} - strategy: - type: Recreate - template: - metadata: - labels: - app: {{ .Values.frontend.serviceName }} - date: {{ now | unixEpoch | quote }} - spec: - containers: - - args: - - sh - - -c - - yarn start - env: - - name: NODE_ENV - value: development - - name: PORT - value: "{{ .Values.frontend.containerPort }}" - - name: REACT_APP_BACKEND_URL - value: {{ include "anythink-tenant.backendHost" .}} - image: "{{ include "anythink-tenant.frontendRepository" .}}:{{ .Values.frontend.image.tag }}" - imagePullPolicy: {{ .Values.frontend.image.pullPolicy }} - name: {{ .Values.frontend.serviceName }} - ports: - - containerPort: {{ .Values.frontend.containerPort }} - name: http - protocol: TCP - startupProbe: - httpGet: - path: / - port: http - failureThreshold: 30 - periodSeconds: 10 - livenessProbe: - httpGet: - path: / - port: http - readinessProbe: - httpGet: - path: / - port: http - resources: - {{- toYaml .Values.frontend.resources | nindent 12 }} - restartPolicy: Always diff --git a/.framework/rails/charts/templates/anythink-frontend-service.yaml b/.framework/rails/charts/templates/anythink-frontend-service.yaml deleted file mode 100644 index 217f8c5..0000000 --- a/.framework/rails/charts/templates/anythink-frontend-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: {{ .Values.frontend.serviceName }} - name: {{ .Values.frontend.serviceName }} -spec: - ports: - - name: "{{ .Values.frontend.containerPort }}" - port: {{ .Values.frontend.containerPort }} - targetPort: {{ .Values.frontend.containerPort }} - selector: - app: {{ .Values.frontend.serviceName }} diff --git a/.framework/rails/charts/templates/database-pvc.yaml b/.framework/rails/charts/templates/database-pvc.yaml deleted file mode 100644 index 88517f3..0000000 --- a/.framework/rails/charts/templates/database-pvc.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app: {{ .Values.database.serviceName }}-0 - name: {{ .Values.database.serviceName }}-0 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Mi diff --git a/.framework/rails/charts/templates/database-service.yaml b/.framework/rails/charts/templates/database-service.yaml deleted file mode 100644 index 80b47d3..0000000 --- a/.framework/rails/charts/templates/database-service.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: {{ .Values.database.serviceName }} - name: {{ .Values.database.serviceName }} -spec: - ports: - - name: "{{ .Values.database.servicePort }}" - port: {{ .Values.database.servicePort }} - targetPort: {{ .Values.database.servicePort }} - selector: - app: {{ .Values.database.serviceName }} diff --git a/.framework/react/frontend/start.sh b/.framework/react/frontend/start.sh deleted file mode 100755 index bca7355..0000000 --- a/.framework/react/frontend/start.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -yarn start diff --git a/.github/.workflows/k8s.yml b/.github/workflows/k8s.yml similarity index 100% rename from .github/.workflows/k8s.yml rename to .github/workflows/k8s.yml diff --git a/.github/workflows/test_e2e_java.yml b/.github/workflows/test_e2e_java.yml deleted file mode 100644 index c68548d..0000000 --- a/.github/workflows/test_e2e_java.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: E2E Java - -on: - pull_request: - -jobs: - ci-checks: - name: Pr checks - runs-on: ubuntu-20.04 - timeout-minutes: 6 - - services: - postgres: - image: postgres:13 - env: - POSTGRES_PASSWORD: postgres - SECRET_KEY: secret - POSTGRES_DB: anythink-market - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - name: Check out project - uses: actions/checkout@v2 - - - uses: actions/setup-java@v4 - with: - working-directory: .framework/java/backend - java-version: 21 - distribution: adopt - - - uses: oNaiPs/secrets-to-env-action@v1 - with: - secrets: ${{ toJSON(secrets) }} - - - run: ./gradlew build - working-directory: .framework/java/backend - - - run: ENGINE_BASE_URL=http://localhost:3003 WILCO_ID=0 SPRING_DATASOURCE_URL=jdbc:postgresql://localhost/anythink-market SPRING_DATASOURCE_USERNAME=postgres SPRING_DATASOURCE_PASSWORD=postgres ./gradlew bootRun >& /dev/null & - working-directory: .framework/java/backend - - - name: Run checks - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - cache-dependency-path: tests/e2e/yarn.lock - - - run: yarn install - working-directory: tests/e2e/ - - - run: yarn wait-on http://localhost:3000/health --timeout 20000 - working-directory: tests/e2e/ - - - run: yarn jest -c jest.sequential.config.js --maxWorkers=1 # TODO skip concurrent tests until fixed - working-directory: tests/e2e/ diff --git a/.github/workflows/test_e2e_lint.yml b/.github/workflows/test_e2e_lint.yml deleted file mode 100644 index 4d8e272..0000000 --- a/.github/workflows/test_e2e_lint.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Lint - -on: - pull_request: - -jobs: - lint: - name: Pr checks - runs-on: ubuntu-20.04 - timeout-minutes: 6 - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} - - - name: Run checks - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - cache-dependency-path: tests/e2e/ - - - run: yarn install - working-directory: tests/e2e - - - run: yarn lint - working-directory: tests/e2e diff --git a/.github/workflows/test_e2e_node.yml b/.github/workflows/test_e2e_node.yml deleted file mode 100644 index a0f363d..0000000 --- a/.github/workflows/test_e2e_node.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: E2E Node - -on: - pull_request: - -jobs: - ci-checks: - name: Pr checks - runs-on: ubuntu-20.04 - timeout-minutes: 6 - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} - - - name: Run checks - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - cache-dependency-path: .framework/node/backend - - - uses: oNaiPs/secrets-to-env-action@v1 - with: - secrets: ${{ toJSON(secrets) }} - - - name: Start MongoDB - uses: supercharge/mongodb-github-action@1.6.0 - with: - mongodb-version: "4.4" - - - run: yarn install - working-directory: .framework/node/backend - - - run: ENGINE_BASE_URL=http://localhost:3003 WILCO_ID=0 MONGODB_URI=mongodb://localhost/anythink-market yarn start >& /dev/null & - working-directory: .framework/node/backend - - - run: yarn install - working-directory: tests/e2e/ - - - run: yarn wait-on http://localhost:3000/health --timeout 5000 - working-directory: tests/e2e/ - - - run: yarn test - working-directory: tests/e2e/ diff --git a/.github/workflows/test_e2e_python.yml b/.github/workflows/test_e2e_python.yml deleted file mode 100644 index e2684b6..0000000 --- a/.github/workflows/test_e2e_python.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: E2E Python - -on: - pull_request: - -jobs: - ci-checks: - name: Pr checks - runs-on: ubuntu-20.04 - timeout-minutes: 6 - - services: - postgres: - image: postgres:13 - env: - POSTGRES_PASSWORD: postgres - SECRET_KEY: secret - POSTGRES_DB: anythink-market - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - name: Check out project - uses: actions/checkout@v2 - - - name: Use Python - uses: actions/setup-python@v4 - with: - python-version: "3.9.13" - cache: 'pip' - - - uses: oNaiPs/secrets-to-env-action@v1 - with: - secrets: ${{ toJSON(secrets) }} - - - run: pip install -r requirements.txt - working-directory: .framework/python/backend - - - run: pip install gunicorn - working-directory: .framework/python/backend - - - name: Run postgres migration - run: SECRET_KEY=secret DATABASE_URL=postgresql://postgres:postgres@localhost/anythink-market alembic upgrade head - working-directory: .framework/python/backend - - - name: Run python server - run: ENGINE_BASE_URL=http://localhost:3003 WILCO_ID=0 SECRET_KEY=secret DATABASE_URL=postgresql://postgres:postgres@localhost/anythink-market gunicorn app.main:app --worker-class=uvicorn.workers.UvicornWorker --bind=0.0.0.0:3000 --workers=5 >& /dev/null & - working-directory: .framework/python/backend - - - name: Run checks - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - cache-dependency-path: tests/e2e/yarn.lock - - - run: yarn install - working-directory: tests/e2e/ - - - run: yarn wait-on -v http-get://0.0.0.0:3000/health --timeout 5000 - working-directory: tests/e2e/ - - - run: yarn test - working-directory: tests/e2e/ diff --git a/.github/workflows/test_e2e_rails.yml b/.github/workflows/test_e2e_rails.yml deleted file mode 100644 index 2c2c6ec..0000000 --- a/.github/workflows/test_e2e_rails.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: E2E Rails - -on: - pull_request: - -jobs: - ci-checks: - name: Pr checks - runs-on: ubuntu-20.04 - timeout-minutes: 6 - - services: - postgres: - image: postgres:13 - env: - POSTGRES_PASSWORD: postgres - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - name: Check out project - uses: actions/checkout@v2 - - - uses: ruby/setup-ruby@v1 - with: - working-directory: .framework/rails/backend - bundler-cache: true - - - uses: oNaiPs/secrets-to-env-action@v1 - with: - secrets: ${{ toJSON(secrets) }} - - - run: bundle install - working-directory: .framework/rails/backend - - - run: DATABASE_URL=postgresql://postgres:postgres@localhost/anythink-market bin/rails db:create db:migrate - working-directory: .framework/rails/backend - - - run: ENGINE_BASE_URL=http://localhost:3003 WILCO_ID=0 DATABASE_URL=postgresql://postgres:postgres@localhost/anythink-market bin/rails s >& /dev/null & - working-directory: .framework/rails/backend - - - name: Run checks - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - cache-dependency-path: tests/e2e/yarn.lock - - - run: yarn install - working-directory: tests/e2e/ - - - run: yarn wait-on http://localhost:3000/health --timeout 5000 - working-directory: tests/e2e/ - - - run: yarn test - working-directory: tests/e2e/ diff --git a/.github/workflows/test_frontend_react.yml b/.github/workflows/test_frontend_react.yml deleted file mode 100644 index 32b89cb..0000000 --- a/.github/workflows/test_frontend_react.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Playwright Tests -on: - pull_request: - -jobs: - test: - timeout-minutes: 6 - runs-on: ubuntu-20.04 - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} - - name: Run checks - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - cache-dependency-path: .framework/react/frontend - - - name: Install dependencies - run: yarn install - working-directory: .framework/react/frontend - - - name: Run frontend client - run: WILCO_ID=0 REACT_APP_BACKEND_URL=http://localhost:3001 yarn start >& /dev/null & - working-directory: .framework/react/frontend - - - name: Install test deps - run: yarn install - working-directory: tests/frontend - - - name: Run Playwright tests - run: yarn test - working-directory: tests/frontend diff --git a/.github/workflows/wilco-actions.yml b/.github/workflows/wilco-actions.yml new file mode 100644 index 0000000..c98ce29 --- /dev/null +++ b/.github/workflows/wilco-actions.yml @@ -0,0 +1,46 @@ +on: + pull_request: + branches: + - main + +jobs: + wilco: + runs-on: ubuntu-20.04 + timeout-minutes: 10 + name: Pr checks + + services: + postgres: + image: postgres:13 + env: + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - name: Check out project + uses: actions/checkout@v2 + + - uses: ruby/setup-ruby@v1 + with: + working-directory: backend + bundler-cache: true + + - uses: oNaiPs/secrets-to-env-action@v1 + with: + secrets: ${{ toJSON(secrets) }} + + - name: Setup Node for Wilco Checks + uses: actions/setup-node@v3 + with: + node-version: "16" + + - name: Wilco checks + id: Wilco + uses: trywilco/actions@main + with: + engine: ${{ secrets.WILCO_ENGINE_URL }} diff --git a/.wilco b/.wilco new file mode 100644 index 0000000..8b3ef93 --- /dev/null +++ b/.wilco @@ -0,0 +1 @@ +66ee04598bd45128baca3d7c \ No newline at end of file diff --git a/.framework/rails/backend/.gitignore b/backend/.gitignore similarity index 100% rename from .framework/rails/backend/.gitignore rename to backend/.gitignore diff --git a/.framework/rails/backend/.ruby-version b/backend/.ruby-version similarity index 100% rename from .framework/rails/backend/.ruby-version rename to backend/.ruby-version diff --git a/.framework/rails/backend/Dockerfile b/backend/Dockerfile similarity index 100% rename from .framework/rails/backend/Dockerfile rename to backend/Dockerfile diff --git a/.framework/rails/backend/Dockerfile.aws b/backend/Dockerfile.aws similarity index 100% rename from .framework/rails/backend/Dockerfile.aws rename to backend/Dockerfile.aws diff --git a/.framework/rails/backend/Gemfile b/backend/Gemfile similarity index 100% rename from .framework/rails/backend/Gemfile rename to backend/Gemfile diff --git a/.framework/rails/backend/Gemfile.lock b/backend/Gemfile.lock similarity index 100% rename from .framework/rails/backend/Gemfile.lock rename to backend/Gemfile.lock diff --git a/.framework/rails/backend/README.md b/backend/README.md similarity index 100% rename from .framework/rails/backend/README.md rename to backend/README.md diff --git a/.framework/rails/backend/Rakefile b/backend/Rakefile similarity index 100% rename from .framework/rails/backend/Rakefile rename to backend/Rakefile diff --git a/.framework/rails/backend/app/assets/config/manifest.js b/backend/app/assets/config/manifest.js similarity index 100% rename from .framework/rails/backend/app/assets/config/manifest.js rename to backend/app/assets/config/manifest.js diff --git a/.framework/node/backend/public/.keep b/backend/app/assets/images/.keep similarity index 100% rename from .framework/node/backend/public/.keep rename to backend/app/assets/images/.keep diff --git a/.framework/rails/backend/app/assets/images/.keep b/backend/app/assets/javascripts/.keep similarity index 100% rename from .framework/rails/backend/app/assets/images/.keep rename to backend/app/assets/javascripts/.keep diff --git a/.framework/rails/backend/app/assets/javascripts/.keep b/backend/app/assets/stylesheets/.keep similarity index 100% rename from .framework/rails/backend/app/assets/javascripts/.keep rename to backend/app/assets/stylesheets/.keep diff --git a/.framework/rails/backend/app/channels/application_cable/channel.rb b/backend/app/channels/application_cable/channel.rb similarity index 100% rename from .framework/rails/backend/app/channels/application_cable/channel.rb rename to backend/app/channels/application_cable/channel.rb diff --git a/.framework/rails/backend/app/channels/application_cable/connection.rb b/backend/app/channels/application_cable/connection.rb similarity index 100% rename from .framework/rails/backend/app/channels/application_cable/connection.rb rename to backend/app/channels/application_cable/connection.rb diff --git a/.framework/rails/backend/app/controllers/application_controller.rb b/backend/app/controllers/application_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/application_controller.rb rename to backend/app/controllers/application_controller.rb diff --git a/.framework/rails/backend/app/controllers/comments_controller.rb b/backend/app/controllers/comments_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/comments_controller.rb rename to backend/app/controllers/comments_controller.rb diff --git a/.framework/rails/backend/app/assets/stylesheets/.keep b/backend/app/controllers/concerns/.keep similarity index 100% rename from .framework/rails/backend/app/assets/stylesheets/.keep rename to backend/app/controllers/concerns/.keep diff --git a/.framework/rails/backend/app/controllers/favorites_controller.rb b/backend/app/controllers/favorites_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/favorites_controller.rb rename to backend/app/controllers/favorites_controller.rb diff --git a/.framework/rails/backend/app/controllers/follows_controller.rb b/backend/app/controllers/follows_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/follows_controller.rb rename to backend/app/controllers/follows_controller.rb diff --git a/.framework/rails/backend/app/controllers/items_controller.rb b/backend/app/controllers/items_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/items_controller.rb rename to backend/app/controllers/items_controller.rb diff --git a/.framework/rails/backend/app/controllers/ping_controller.rb b/backend/app/controllers/ping_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/ping_controller.rb rename to backend/app/controllers/ping_controller.rb diff --git a/.framework/rails/backend/app/controllers/profiles_controller.rb b/backend/app/controllers/profiles_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/profiles_controller.rb rename to backend/app/controllers/profiles_controller.rb diff --git a/.framework/rails/backend/app/controllers/registrations_controller.rb b/backend/app/controllers/registrations_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/registrations_controller.rb rename to backend/app/controllers/registrations_controller.rb diff --git a/.framework/rails/backend/app/controllers/sessions_controller.rb b/backend/app/controllers/sessions_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/sessions_controller.rb rename to backend/app/controllers/sessions_controller.rb diff --git a/.framework/rails/backend/app/controllers/tags_controller.rb b/backend/app/controllers/tags_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/tags_controller.rb rename to backend/app/controllers/tags_controller.rb diff --git a/.framework/rails/backend/app/controllers/users_controller.rb b/backend/app/controllers/users_controller.rb similarity index 100% rename from .framework/rails/backend/app/controllers/users_controller.rb rename to backend/app/controllers/users_controller.rb diff --git a/.framework/rails/backend/app/helpers/application_helper.rb b/backend/app/helpers/application_helper.rb similarity index 100% rename from .framework/rails/backend/app/helpers/application_helper.rb rename to backend/app/helpers/application_helper.rb diff --git a/.framework/rails/backend/app/jobs/application_job.rb b/backend/app/jobs/application_job.rb similarity index 100% rename from .framework/rails/backend/app/jobs/application_job.rb rename to backend/app/jobs/application_job.rb diff --git a/.framework/rails/backend/app/mailers/application_mailer.rb b/backend/app/mailers/application_mailer.rb similarity index 100% rename from .framework/rails/backend/app/mailers/application_mailer.rb rename to backend/app/mailers/application_mailer.rb diff --git a/.framework/rails/backend/app/models/application_record.rb b/backend/app/models/application_record.rb similarity index 100% rename from .framework/rails/backend/app/models/application_record.rb rename to backend/app/models/application_record.rb diff --git a/.framework/rails/backend/app/models/comment.rb b/backend/app/models/comment.rb similarity index 100% rename from .framework/rails/backend/app/models/comment.rb rename to backend/app/models/comment.rb diff --git a/.framework/rails/backend/app/controllers/concerns/.keep b/backend/app/models/concerns/.keep similarity index 100% rename from .framework/rails/backend/app/controllers/concerns/.keep rename to backend/app/models/concerns/.keep diff --git a/.framework/rails/backend/app/models/favorite.rb b/backend/app/models/favorite.rb similarity index 100% rename from .framework/rails/backend/app/models/favorite.rb rename to backend/app/models/favorite.rb diff --git a/.framework/rails/backend/app/models/follow.rb b/backend/app/models/follow.rb similarity index 100% rename from .framework/rails/backend/app/models/follow.rb rename to backend/app/models/follow.rb diff --git a/.framework/rails/backend/app/models/item.rb b/backend/app/models/item.rb similarity index 100% rename from .framework/rails/backend/app/models/item.rb rename to backend/app/models/item.rb diff --git a/.framework/rails/backend/app/models/user.rb b/backend/app/models/user.rb similarity index 100% rename from .framework/rails/backend/app/models/user.rb rename to backend/app/models/user.rb diff --git a/.framework/rails/backend/app/views/comments/_comment.json.jbuilder b/backend/app/views/comments/_comment.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/comments/_comment.json.jbuilder rename to backend/app/views/comments/_comment.json.jbuilder diff --git a/.framework/rails/backend/app/views/comments/create.json.jbuilder b/backend/app/views/comments/create.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/comments/create.json.jbuilder rename to backend/app/views/comments/create.json.jbuilder diff --git a/.framework/rails/backend/app/views/comments/index.json.jbuilder b/backend/app/views/comments/index.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/comments/index.json.jbuilder rename to backend/app/views/comments/index.json.jbuilder diff --git a/.framework/rails/backend/app/views/devise/registrations/create.json.jbuilder b/backend/app/views/devise/registrations/create.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/devise/registrations/create.json.jbuilder rename to backend/app/views/devise/registrations/create.json.jbuilder diff --git a/.framework/rails/backend/app/views/devise/sessions/create.json.jbuilder b/backend/app/views/devise/sessions/create.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/devise/sessions/create.json.jbuilder rename to backend/app/views/devise/sessions/create.json.jbuilder diff --git a/.framework/rails/backend/app/views/items/_item.json.jbuilder b/backend/app/views/items/_item.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/items/_item.json.jbuilder rename to backend/app/views/items/_item.json.jbuilder diff --git a/.framework/rails/backend/app/views/items/index.json.jbuilder b/backend/app/views/items/index.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/items/index.json.jbuilder rename to backend/app/views/items/index.json.jbuilder diff --git a/.framework/rails/backend/app/views/items/show.json.jbuilder b/backend/app/views/items/show.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/items/show.json.jbuilder rename to backend/app/views/items/show.json.jbuilder diff --git a/.framework/rails/backend/app/views/profiles/_profile.json.jbuilder b/backend/app/views/profiles/_profile.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/profiles/_profile.json.jbuilder rename to backend/app/views/profiles/_profile.json.jbuilder diff --git a/.framework/rails/backend/app/views/profiles/show.json.jbuilder b/backend/app/views/profiles/show.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/profiles/show.json.jbuilder rename to backend/app/views/profiles/show.json.jbuilder diff --git a/.framework/rails/backend/app/views/users/_user.json.jbuilder b/backend/app/views/users/_user.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/users/_user.json.jbuilder rename to backend/app/views/users/_user.json.jbuilder diff --git a/.framework/rails/backend/app/views/users/show.json.jbuilder b/backend/app/views/users/show.json.jbuilder similarity index 100% rename from .framework/rails/backend/app/views/users/show.json.jbuilder rename to backend/app/views/users/show.json.jbuilder diff --git a/.framework/rails/backend/bin/bundle b/backend/bin/bundle similarity index 100% rename from .framework/rails/backend/bin/bundle rename to backend/bin/bundle diff --git a/.framework/rails/backend/bin/heroku_release.sh b/backend/bin/heroku_release.sh similarity index 100% rename from .framework/rails/backend/bin/heroku_release.sh rename to backend/bin/heroku_release.sh diff --git a/.framework/rails/backend/bin/rails b/backend/bin/rails similarity index 100% rename from .framework/rails/backend/bin/rails rename to backend/bin/rails diff --git a/.framework/rails/backend/bin/rake b/backend/bin/rake similarity index 100% rename from .framework/rails/backend/bin/rake rename to backend/bin/rake diff --git a/.framework/rails/backend/bin/setup b/backend/bin/setup similarity index 100% rename from .framework/rails/backend/bin/setup rename to backend/bin/setup diff --git a/.framework/rails/backend/bin/spring b/backend/bin/spring similarity index 100% rename from .framework/rails/backend/bin/spring rename to backend/bin/spring diff --git a/.framework/rails/backend/bin/update b/backend/bin/update similarity index 100% rename from .framework/rails/backend/bin/update rename to backend/bin/update diff --git a/.framework/rails/backend/bin/yarn b/backend/bin/yarn similarity index 100% rename from .framework/rails/backend/bin/yarn rename to backend/bin/yarn diff --git a/.framework/rails/backend/config.ru b/backend/config.ru similarity index 100% rename from .framework/rails/backend/config.ru rename to backend/config.ru diff --git a/.framework/rails/backend/config/application.rb b/backend/config/application.rb similarity index 100% rename from .framework/rails/backend/config/application.rb rename to backend/config/application.rb diff --git a/.framework/rails/backend/config/boot.rb b/backend/config/boot.rb similarity index 100% rename from .framework/rails/backend/config/boot.rb rename to backend/config/boot.rb diff --git a/.framework/rails/backend/config/cable.yml b/backend/config/cable.yml similarity index 100% rename from .framework/rails/backend/config/cable.yml rename to backend/config/cable.yml diff --git a/.framework/rails/backend/config/credentials.yml.enc b/backend/config/credentials.yml.enc similarity index 100% rename from .framework/rails/backend/config/credentials.yml.enc rename to backend/config/credentials.yml.enc diff --git a/.framework/rails/backend/config/database.yml b/backend/config/database.yml similarity index 100% rename from .framework/rails/backend/config/database.yml rename to backend/config/database.yml diff --git a/.framework/rails/backend/config/environment.rb b/backend/config/environment.rb similarity index 100% rename from .framework/rails/backend/config/environment.rb rename to backend/config/environment.rb diff --git a/.framework/rails/backend/config/environments/development.rb b/backend/config/environments/development.rb similarity index 100% rename from .framework/rails/backend/config/environments/development.rb rename to backend/config/environments/development.rb diff --git a/.framework/rails/backend/config/environments/production.rb b/backend/config/environments/production.rb similarity index 100% rename from .framework/rails/backend/config/environments/production.rb rename to backend/config/environments/production.rb diff --git a/.framework/rails/backend/config/environments/test.rb b/backend/config/environments/test.rb similarity index 100% rename from .framework/rails/backend/config/environments/test.rb rename to backend/config/environments/test.rb diff --git a/.framework/rails/backend/config/initializers/application_controller_renderer.rb b/backend/config/initializers/application_controller_renderer.rb similarity index 100% rename from .framework/rails/backend/config/initializers/application_controller_renderer.rb rename to backend/config/initializers/application_controller_renderer.rb diff --git a/.framework/rails/backend/config/initializers/assets.rb b/backend/config/initializers/assets.rb similarity index 100% rename from .framework/rails/backend/config/initializers/assets.rb rename to backend/config/initializers/assets.rb diff --git a/.framework/rails/backend/config/initializers/backtrace_silencers.rb b/backend/config/initializers/backtrace_silencers.rb similarity index 100% rename from .framework/rails/backend/config/initializers/backtrace_silencers.rb rename to backend/config/initializers/backtrace_silencers.rb diff --git a/.framework/rails/backend/config/initializers/content_security_policy.rb b/backend/config/initializers/content_security_policy.rb similarity index 100% rename from .framework/rails/backend/config/initializers/content_security_policy.rb rename to backend/config/initializers/content_security_policy.rb diff --git a/.framework/rails/backend/config/initializers/cookies_serializer.rb b/backend/config/initializers/cookies_serializer.rb similarity index 100% rename from .framework/rails/backend/config/initializers/cookies_serializer.rb rename to backend/config/initializers/cookies_serializer.rb diff --git a/.framework/rails/backend/config/initializers/cors.rb b/backend/config/initializers/cors.rb similarity index 100% rename from .framework/rails/backend/config/initializers/cors.rb rename to backend/config/initializers/cors.rb diff --git a/.framework/rails/backend/config/initializers/devise.rb b/backend/config/initializers/devise.rb similarity index 100% rename from .framework/rails/backend/config/initializers/devise.rb rename to backend/config/initializers/devise.rb diff --git a/.framework/rails/backend/config/initializers/filter_parameter_logging.rb b/backend/config/initializers/filter_parameter_logging.rb similarity index 100% rename from .framework/rails/backend/config/initializers/filter_parameter_logging.rb rename to backend/config/initializers/filter_parameter_logging.rb diff --git a/.framework/rails/backend/config/initializers/inflections.rb b/backend/config/initializers/inflections.rb similarity index 100% rename from .framework/rails/backend/config/initializers/inflections.rb rename to backend/config/initializers/inflections.rb diff --git a/.framework/rails/backend/config/initializers/json_param_key_transform.rb b/backend/config/initializers/json_param_key_transform.rb similarity index 100% rename from .framework/rails/backend/config/initializers/json_param_key_transform.rb rename to backend/config/initializers/json_param_key_transform.rb diff --git a/.framework/rails/backend/config/initializers/mime_types.rb b/backend/config/initializers/mime_types.rb similarity index 100% rename from .framework/rails/backend/config/initializers/mime_types.rb rename to backend/config/initializers/mime_types.rb diff --git a/.framework/rails/backend/config/initializers/wrap_parameters.rb b/backend/config/initializers/wrap_parameters.rb similarity index 100% rename from .framework/rails/backend/config/initializers/wrap_parameters.rb rename to backend/config/initializers/wrap_parameters.rb diff --git a/.framework/rails/backend/config/locales/devise.en.yml b/backend/config/locales/devise.en.yml similarity index 100% rename from .framework/rails/backend/config/locales/devise.en.yml rename to backend/config/locales/devise.en.yml diff --git a/.framework/rails/backend/config/locales/en.yml b/backend/config/locales/en.yml similarity index 100% rename from .framework/rails/backend/config/locales/en.yml rename to backend/config/locales/en.yml diff --git a/.framework/rails/backend/config/locales/responders.en.yml b/backend/config/locales/responders.en.yml similarity index 100% rename from .framework/rails/backend/config/locales/responders.en.yml rename to backend/config/locales/responders.en.yml diff --git a/.framework/rails/backend/config/puma.rb b/backend/config/puma.rb similarity index 100% rename from .framework/rails/backend/config/puma.rb rename to backend/config/puma.rb diff --git a/.framework/rails/backend/config/routes.rb b/backend/config/routes.rb similarity index 100% rename from .framework/rails/backend/config/routes.rb rename to backend/config/routes.rb diff --git a/.framework/rails/backend/config/secrets.yml b/backend/config/secrets.yml similarity index 100% rename from .framework/rails/backend/config/secrets.yml rename to backend/config/secrets.yml diff --git a/.framework/rails/backend/config/secrets.yml.enc b/backend/config/secrets.yml.enc similarity index 100% rename from .framework/rails/backend/config/secrets.yml.enc rename to backend/config/secrets.yml.enc diff --git a/.framework/rails/backend/config/spring.rb b/backend/config/spring.rb similarity index 100% rename from .framework/rails/backend/config/spring.rb rename to backend/config/spring.rb diff --git a/.framework/rails/backend/config/storage.yml b/backend/config/storage.yml similarity index 100% rename from .framework/rails/backend/config/storage.yml rename to backend/config/storage.yml diff --git a/.framework/rails/backend/db/migrate/20210412045707_devise_create_users.rb b/backend/db/migrate/20210412045707_devise_create_users.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412045707_devise_create_users.rb rename to backend/db/migrate/20210412045707_devise_create_users.rb diff --git a/.framework/rails/backend/db/migrate/20210412045739_add_profile_fields_to_users.rb b/backend/db/migrate/20210412045739_add_profile_fields_to_users.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412045739_add_profile_fields_to_users.rb rename to backend/db/migrate/20210412045739_add_profile_fields_to_users.rb diff --git a/.framework/rails/backend/db/migrate/20210412052128_create_items.rb b/backend/db/migrate/20210412052128_create_items.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412052128_create_items.rb rename to backend/db/migrate/20210412052128_create_items.rb diff --git a/.framework/rails/backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb rename to backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb diff --git a/.framework/rails/backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb rename to backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb diff --git a/.framework/rails/backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb rename to backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb diff --git a/.framework/rails/backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb rename to backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb diff --git a/.framework/rails/backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb rename to backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb diff --git a/.framework/rails/backend/db/migrate/20210412055201_create_favorites.rb b/backend/db/migrate/20210412055201_create_favorites.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412055201_create_favorites.rb rename to backend/db/migrate/20210412055201_create_favorites.rb diff --git a/.framework/rails/backend/db/migrate/20210412061113_create_comments.rb b/backend/db/migrate/20210412061113_create_comments.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412061113_create_comments.rb rename to backend/db/migrate/20210412061113_create_comments.rb diff --git a/.framework/rails/backend/db/migrate/20210412061614_acts_as_follower_migration.rb b/backend/db/migrate/20210412061614_acts_as_follower_migration.rb similarity index 100% rename from .framework/rails/backend/db/migrate/20210412061614_acts_as_follower_migration.rb rename to backend/db/migrate/20210412061614_acts_as_follower_migration.rb diff --git a/.framework/rails/backend/db/schema.rb b/backend/db/schema.rb similarity index 100% rename from .framework/rails/backend/db/schema.rb rename to backend/db/schema.rb diff --git a/.framework/rails/backend/db/seeds.rb b/backend/db/seeds.rb similarity index 100% rename from .framework/rails/backend/db/seeds.rb rename to backend/db/seeds.rb diff --git a/.framework/rails/backend/app/models/concerns/.keep b/backend/lib/assets/.keep similarity index 100% rename from .framework/rails/backend/app/models/concerns/.keep rename to backend/lib/assets/.keep diff --git a/.framework/rails/backend/lib/event.rb b/backend/lib/event.rb similarity index 100% rename from .framework/rails/backend/lib/event.rb rename to backend/lib/event.rb diff --git a/.framework/rails/backend/lib/assets/.keep b/backend/lib/tasks/.keep similarity index 100% rename from .framework/rails/backend/lib/assets/.keep rename to backend/lib/tasks/.keep diff --git a/.framework/rails/backend/lib/tasks/.keep b/backend/log/.keep similarity index 100% rename from .framework/rails/backend/lib/tasks/.keep rename to backend/log/.keep diff --git a/.framework/rails/backend/public/404.html b/backend/public/404.html similarity index 100% rename from .framework/rails/backend/public/404.html rename to backend/public/404.html diff --git a/.framework/rails/backend/public/422.html b/backend/public/422.html similarity index 100% rename from .framework/rails/backend/public/422.html rename to backend/public/422.html diff --git a/.framework/rails/backend/public/500.html b/backend/public/500.html similarity index 100% rename from .framework/rails/backend/public/500.html rename to backend/public/500.html diff --git a/.framework/rails/backend/public/favicon.ico b/backend/public/favicon.ico similarity index 100% rename from .framework/rails/backend/public/favicon.ico rename to backend/public/favicon.ico diff --git a/.framework/rails/backend/public/robots.txt b/backend/public/robots.txt similarity index 100% rename from .framework/rails/backend/public/robots.txt rename to backend/public/robots.txt diff --git a/.framework/rails/backend/seeds.sh b/backend/seeds.sh similarity index 100% rename from .framework/rails/backend/seeds.sh rename to backend/seeds.sh diff --git a/.framework/rails/backend/start.sh b/backend/start.sh similarity index 100% rename from .framework/rails/backend/start.sh rename to backend/start.sh diff --git a/.framework/rails/backend/start_rails.sh b/backend/start_rails.sh similarity index 100% rename from .framework/rails/backend/start_rails.sh rename to backend/start_rails.sh diff --git a/.framework/rails/backend/log/.keep b/backend/vendor/.keep similarity index 100% rename from .framework/rails/backend/log/.keep rename to backend/vendor/.keep diff --git a/.framework/java/charts/.helmignore b/charts/.helmignore similarity index 100% rename from .framework/java/charts/.helmignore rename to charts/.helmignore diff --git a/.framework/java/charts/Chart.yaml b/charts/Chart.yaml similarity index 100% rename from .framework/java/charts/Chart.yaml rename to charts/Chart.yaml diff --git a/.framework/java/charts/templates/_helpers.yml b/charts/templates/_helpers.yml similarity index 100% rename from .framework/java/charts/templates/_helpers.yml rename to charts/templates/_helpers.yml diff --git a/.framework/rails/charts/templates/anythink-backend-deployment.yaml b/charts/templates/anythink-backend-deployment.yaml similarity index 100% rename from .framework/rails/charts/templates/anythink-backend-deployment.yaml rename to charts/templates/anythink-backend-deployment.yaml diff --git a/.framework/java/charts/templates/anythink-backend-service.yaml b/charts/templates/anythink-backend-service.yaml similarity index 100% rename from .framework/java/charts/templates/anythink-backend-service.yaml rename to charts/templates/anythink-backend-service.yaml diff --git a/.framework/java/charts/templates/anythink-frontend-deployment.yaml b/charts/templates/anythink-frontend-deployment.yaml similarity index 100% rename from .framework/java/charts/templates/anythink-frontend-deployment.yaml rename to charts/templates/anythink-frontend-deployment.yaml diff --git a/.framework/java/charts/templates/anythink-frontend-service.yaml b/charts/templates/anythink-frontend-service.yaml similarity index 100% rename from .framework/java/charts/templates/anythink-frontend-service.yaml rename to charts/templates/anythink-frontend-service.yaml diff --git a/.framework/rails/charts/templates/database-deployment.yaml b/charts/templates/database-deployment.yaml similarity index 100% rename from .framework/rails/charts/templates/database-deployment.yaml rename to charts/templates/database-deployment.yaml diff --git a/.framework/java/charts/templates/database-pvc.yaml b/charts/templates/database-pvc.yaml similarity index 100% rename from .framework/java/charts/templates/database-pvc.yaml rename to charts/templates/database-pvc.yaml diff --git a/.framework/java/charts/templates/database-service.yaml b/charts/templates/database-service.yaml similarity index 100% rename from .framework/java/charts/templates/database-service.yaml rename to charts/templates/database-service.yaml diff --git a/.framework/rails/charts/values.yaml b/charts/values.yaml similarity index 100% rename from .framework/rails/charts/values.yaml rename to charts/values.yaml diff --git a/.framework/rails/docker-compose.yml b/docker-compose.yml similarity index 100% rename from .framework/rails/docker-compose.yml rename to docker-compose.yml diff --git a/.framework/react/frontend/.eslintignore b/frontend/.eslintignore similarity index 100% rename from .framework/react/frontend/.eslintignore rename to frontend/.eslintignore diff --git a/.framework/react/frontend/.gitignore b/frontend/.gitignore similarity index 100% rename from .framework/react/frontend/.gitignore rename to frontend/.gitignore diff --git a/.framework/react/frontend/Dockerfile b/frontend/Dockerfile similarity index 100% rename from .framework/react/frontend/Dockerfile rename to frontend/Dockerfile diff --git a/.framework/react/frontend/Dockerfile.aws b/frontend/Dockerfile.aws similarity index 100% rename from .framework/react/frontend/Dockerfile.aws rename to frontend/Dockerfile.aws diff --git a/.framework/react/frontend/jest.config.js b/frontend/jest.config.js similarity index 100% rename from .framework/react/frontend/jest.config.js rename to frontend/jest.config.js diff --git a/.framework/react/frontend/package.json b/frontend/package.json similarity index 100% rename from .framework/react/frontend/package.json rename to frontend/package.json diff --git a/.framework/react/frontend/public/50precentoff.png b/frontend/public/50precentoff.png similarity index 100% rename from .framework/react/frontend/public/50precentoff.png rename to frontend/public/50precentoff.png diff --git a/.framework/react/frontend/public/favicon.ico b/frontend/public/favicon.ico similarity index 100% rename from .framework/react/frontend/public/favicon.ico rename to frontend/public/favicon.ico diff --git a/.framework/react/frontend/public/index.html b/frontend/public/index.html similarity index 100% rename from .framework/react/frontend/public/index.html rename to frontend/public/index.html diff --git a/.framework/react/frontend/public/placeholder.png b/frontend/public/placeholder.png similarity index 100% rename from .framework/react/frontend/public/placeholder.png rename to frontend/public/placeholder.png diff --git a/.framework/react/frontend/public/style.css b/frontend/public/style.css similarity index 100% rename from .framework/react/frontend/public/style.css rename to frontend/public/style.css diff --git a/.framework/react/frontend/public/sunray.jpeg b/frontend/public/sunray.jpeg similarity index 100% rename from .framework/react/frontend/public/sunray.jpeg rename to frontend/public/sunray.jpeg diff --git a/.framework/react/frontend/public/verified_seller.svg b/frontend/public/verified_seller.svg similarity index 100% rename from .framework/react/frontend/public/verified_seller.svg rename to frontend/public/verified_seller.svg diff --git a/.framework/react/frontend/readme.md b/frontend/readme.md similarity index 100% rename from .framework/react/frontend/readme.md rename to frontend/readme.md diff --git a/.framework/react/frontend/src/agent.js b/frontend/src/agent.js similarity index 100% rename from .framework/react/frontend/src/agent.js rename to frontend/src/agent.js diff --git a/.framework/react/frontend/src/components/App.js b/frontend/src/components/App.js similarity index 100% rename from .framework/react/frontend/src/components/App.js rename to frontend/src/components/App.js diff --git a/.framework/react/frontend/src/components/Editor.js b/frontend/src/components/Editor.js similarity index 100% rename from .framework/react/frontend/src/components/Editor.js rename to frontend/src/components/Editor.js diff --git a/.framework/react/frontend/src/components/Header.js b/frontend/src/components/Header.js similarity index 100% rename from .framework/react/frontend/src/components/Header.js rename to frontend/src/components/Header.js diff --git a/.framework/react/frontend/src/components/Home/Banner.js b/frontend/src/components/Home/Banner.js similarity index 100% rename from .framework/react/frontend/src/components/Home/Banner.js rename to frontend/src/components/Home/Banner.js diff --git a/.framework/react/frontend/src/components/Home/MainView.js b/frontend/src/components/Home/MainView.js similarity index 100% rename from .framework/react/frontend/src/components/Home/MainView.js rename to frontend/src/components/Home/MainView.js diff --git a/.framework/react/frontend/src/components/Home/Tags.js b/frontend/src/components/Home/Tags.js similarity index 100% rename from .framework/react/frontend/src/components/Home/Tags.js rename to frontend/src/components/Home/Tags.js diff --git a/.framework/react/frontend/src/components/Home/index.js b/frontend/src/components/Home/index.js similarity index 100% rename from .framework/react/frontend/src/components/Home/index.js rename to frontend/src/components/Home/index.js diff --git a/.framework/react/frontend/src/components/Item/Comment.js b/frontend/src/components/Item/Comment.js similarity index 100% rename from .framework/react/frontend/src/components/Item/Comment.js rename to frontend/src/components/Item/Comment.js diff --git a/.framework/react/frontend/src/components/Item/CommentContainer.js b/frontend/src/components/Item/CommentContainer.js similarity index 100% rename from .framework/react/frontend/src/components/Item/CommentContainer.js rename to frontend/src/components/Item/CommentContainer.js diff --git a/.framework/react/frontend/src/components/Item/CommentInput.js b/frontend/src/components/Item/CommentInput.js similarity index 100% rename from .framework/react/frontend/src/components/Item/CommentInput.js rename to frontend/src/components/Item/CommentInput.js diff --git a/.framework/react/frontend/src/components/Item/CommentList.js b/frontend/src/components/Item/CommentList.js similarity index 100% rename from .framework/react/frontend/src/components/Item/CommentList.js rename to frontend/src/components/Item/CommentList.js diff --git a/.framework/react/frontend/src/components/Item/DeleteButton.js b/frontend/src/components/Item/DeleteButton.js similarity index 100% rename from .framework/react/frontend/src/components/Item/DeleteButton.js rename to frontend/src/components/Item/DeleteButton.js diff --git a/.framework/react/frontend/src/components/Item/ItemActions.js b/frontend/src/components/Item/ItemActions.js similarity index 100% rename from .framework/react/frontend/src/components/Item/ItemActions.js rename to frontend/src/components/Item/ItemActions.js diff --git a/.framework/react/frontend/src/components/Item/ItemMeta.js b/frontend/src/components/Item/ItemMeta.js similarity index 100% rename from .framework/react/frontend/src/components/Item/ItemMeta.js rename to frontend/src/components/Item/ItemMeta.js diff --git a/.framework/react/frontend/src/components/Item/index.js b/frontend/src/components/Item/index.js similarity index 100% rename from .framework/react/frontend/src/components/Item/index.js rename to frontend/src/components/Item/index.js diff --git a/.framework/react/frontend/src/components/Item/utils/ItemFetcher.js b/frontend/src/components/Item/utils/ItemFetcher.js similarity index 100% rename from .framework/react/frontend/src/components/Item/utils/ItemFetcher.js rename to frontend/src/components/Item/utils/ItemFetcher.js diff --git a/.framework/react/frontend/src/components/ItemList.js b/frontend/src/components/ItemList.js similarity index 100% rename from .framework/react/frontend/src/components/ItemList.js rename to frontend/src/components/ItemList.js diff --git a/.framework/react/frontend/src/components/ItemPreview.js b/frontend/src/components/ItemPreview.js similarity index 100% rename from .framework/react/frontend/src/components/ItemPreview.js rename to frontend/src/components/ItemPreview.js diff --git a/.framework/react/frontend/src/components/ListErrors.js b/frontend/src/components/ListErrors.js similarity index 100% rename from .framework/react/frontend/src/components/ListErrors.js rename to frontend/src/components/ListErrors.js diff --git a/.framework/react/frontend/src/components/ListPagination.js b/frontend/src/components/ListPagination.js similarity index 100% rename from .framework/react/frontend/src/components/ListPagination.js rename to frontend/src/components/ListPagination.js diff --git a/.framework/react/frontend/src/components/Login.js b/frontend/src/components/Login.js similarity index 100% rename from .framework/react/frontend/src/components/Login.js rename to frontend/src/components/Login.js diff --git a/.framework/react/frontend/src/components/Profile.js b/frontend/src/components/Profile.js similarity index 100% rename from .framework/react/frontend/src/components/Profile.js rename to frontend/src/components/Profile.js diff --git a/.framework/react/frontend/src/components/ProfileFavorites.js b/frontend/src/components/ProfileFavorites.js similarity index 100% rename from .framework/react/frontend/src/components/ProfileFavorites.js rename to frontend/src/components/ProfileFavorites.js diff --git a/.framework/react/frontend/src/components/Register.js b/frontend/src/components/Register.js similarity index 100% rename from .framework/react/frontend/src/components/Register.js rename to frontend/src/components/Register.js diff --git a/.framework/react/frontend/src/components/Settings.js b/frontend/src/components/Settings.js similarity index 100% rename from .framework/react/frontend/src/components/Settings.js rename to frontend/src/components/Settings.js diff --git a/.framework/react/frontend/src/components/commons.js b/frontend/src/components/commons.js similarity index 100% rename from .framework/react/frontend/src/components/commons.js rename to frontend/src/components/commons.js diff --git a/.framework/react/frontend/src/constants/actionTypes.js b/frontend/src/constants/actionTypes.js similarity index 100% rename from .framework/react/frontend/src/constants/actionTypes.js rename to frontend/src/constants/actionTypes.js diff --git a/.framework/react/frontend/src/custom.scss b/frontend/src/custom.scss similarity index 100% rename from .framework/react/frontend/src/custom.scss rename to frontend/src/custom.scss diff --git a/.framework/react/frontend/src/imgs/background.png b/frontend/src/imgs/background.png similarity index 100% rename from .framework/react/frontend/src/imgs/background.png rename to frontend/src/imgs/background.png diff --git a/.framework/react/frontend/src/imgs/logo.png b/frontend/src/imgs/logo.png similarity index 100% rename from .framework/react/frontend/src/imgs/logo.png rename to frontend/src/imgs/logo.png diff --git a/.framework/react/frontend/src/imgs/topbar_logo.png b/frontend/src/imgs/topbar_logo.png similarity index 100% rename from .framework/react/frontend/src/imgs/topbar_logo.png rename to frontend/src/imgs/topbar_logo.png diff --git a/.framework/react/frontend/src/index.js b/frontend/src/index.js similarity index 100% rename from .framework/react/frontend/src/index.js rename to frontend/src/index.js diff --git a/.framework/react/frontend/src/middleware.js b/frontend/src/middleware.js similarity index 100% rename from .framework/react/frontend/src/middleware.js rename to frontend/src/middleware.js diff --git a/.framework/react/frontend/src/reducer.js b/frontend/src/reducer.js similarity index 100% rename from .framework/react/frontend/src/reducer.js rename to frontend/src/reducer.js diff --git a/.framework/react/frontend/src/reducers/auth.js b/frontend/src/reducers/auth.js similarity index 100% rename from .framework/react/frontend/src/reducers/auth.js rename to frontend/src/reducers/auth.js diff --git a/.framework/react/frontend/src/reducers/common.js b/frontend/src/reducers/common.js similarity index 100% rename from .framework/react/frontend/src/reducers/common.js rename to frontend/src/reducers/common.js diff --git a/.framework/react/frontend/src/reducers/editor.js b/frontend/src/reducers/editor.js similarity index 100% rename from .framework/react/frontend/src/reducers/editor.js rename to frontend/src/reducers/editor.js diff --git a/.framework/react/frontend/src/reducers/home.js b/frontend/src/reducers/home.js similarity index 100% rename from .framework/react/frontend/src/reducers/home.js rename to frontend/src/reducers/home.js diff --git a/.framework/react/frontend/src/reducers/item.js b/frontend/src/reducers/item.js similarity index 100% rename from .framework/react/frontend/src/reducers/item.js rename to frontend/src/reducers/item.js diff --git a/.framework/react/frontend/src/reducers/itemList.js b/frontend/src/reducers/itemList.js similarity index 100% rename from .framework/react/frontend/src/reducers/itemList.js rename to frontend/src/reducers/itemList.js diff --git a/.framework/react/frontend/src/reducers/profile.js b/frontend/src/reducers/profile.js similarity index 100% rename from .framework/react/frontend/src/reducers/profile.js rename to frontend/src/reducers/profile.js diff --git a/.framework/react/frontend/src/reducers/settings.js b/frontend/src/reducers/settings.js similarity index 100% rename from .framework/react/frontend/src/reducers/settings.js rename to frontend/src/reducers/settings.js diff --git a/.framework/react/frontend/src/setupTests.js b/frontend/src/setupTests.js similarity index 100% rename from .framework/react/frontend/src/setupTests.js rename to frontend/src/setupTests.js diff --git a/.framework/react/frontend/src/store.js b/frontend/src/store.js similarity index 100% rename from .framework/react/frontend/src/store.js rename to frontend/src/store.js diff --git a/.framework/react/frontend/src/tests/components/Header.test.js b/frontend/src/tests/components/Header.test.js similarity index 100% rename from .framework/react/frontend/src/tests/components/Header.test.js rename to frontend/src/tests/components/Header.test.js diff --git a/.framework/react/frontend/src/tests/components/__snapshots__/Header.test.js.snap b/frontend/src/tests/components/__snapshots__/Header.test.js.snap similarity index 100% rename from .framework/react/frontend/src/tests/components/__snapshots__/Header.test.js.snap rename to frontend/src/tests/components/__snapshots__/Header.test.js.snap diff --git a/.framework/react/frontend/src/tests/item/CommentInput.test.js b/frontend/src/tests/item/CommentInput.test.js similarity index 100% rename from .framework/react/frontend/src/tests/item/CommentInput.test.js rename to frontend/src/tests/item/CommentInput.test.js diff --git a/.framework/react/frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap b/frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap similarity index 100% rename from .framework/react/frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap rename to frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap diff --git a/.framework/node/backend/start.sh b/frontend/start.sh similarity index 100% rename from .framework/node/backend/start.sh rename to frontend/start.sh diff --git a/.framework/react/frontend/yarn.lock b/frontend/yarn.lock similarity index 100% rename from .framework/react/frontend/yarn.lock rename to frontend/yarn.lock