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/.devcontainer/setup.sh b/.devcontainer/setup.sh index 5a6cfc3..80171cc 100755 --- a/.devcontainer/setup.sh +++ b/.devcontainer/setup.sh @@ -1,7 +1,8 @@ WILCO_ID="`cat .wilco`" +ENGINE_EVENT_ENDPOINT="${ENGINE_BASE_URL}/users/${WILCO_ID}/event" +ENGINE_WILCO_AI_CONFIG="${ENGINE_BASE_URL}/users/${WILCO_ID}/wilcoAiConfig" CODESPACE_BACKEND_HOST=$(curl -s "${ENGINE_BASE_URL}/api/v1/codespace/backendHost?codespaceName=${CODESPACE_NAME}&portForwarding=${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}" | jq -r '.codespaceBackendHost') CODESPACE_BACKEND_URL="https://${CODESPACE_BACKEND_HOST}" -export ENGINE_EVENT_ENDPOINT="${ENGINE_BASE_URL}/users/${WILCO_ID}/event" # Update engine that codespace started for user curl -L -X POST "${ENGINE_EVENT_ENDPOINT}" -H "Content-Type: application/json" --data-raw "{ \"event\": \"github_codespace_started\" }" @@ -9,10 +10,16 @@ curl -L -X POST "${ENGINE_EVENT_ENDPOINT}" -H "Content-Type: application/json" - # Export backend envs when in codespaces echo "export CODESPACE_BACKEND_HOST=\"${CODESPACE_BACKEND_HOST}\"" >> ~/.bashrc echo "export CODESPACE_BACKEND_URL=\"${CODESPACE_BACKEND_URL}\"" >> ~/.bashrc +echo "export ENGINE_WILCO_AI_URL=\"${ENGINE_WILCO_AI_CONFIG}\"" >> ~/.bashrc echo "export CODESPACE_WDS_SOCKET_PORT=443" >> ~/.bashrc +# Install the Atlas CLI +curl -fsSL https://pgp.mongodb.com/server-7.0.asc | \ +sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb-server-7.0.gpg && +echo "deb [ arch=amd64,arm64 signed=/etc/apt/trusted.gpg.d/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list && +sudo apt-get update && +sudo apt-get install -y mongodb-atlas-cli + # Export welcome prompt in bash: echo "printf \"\n\n☁️☁️☁️️ Anythink: Develop in the Cloud ☁️☁️☁️\n\"" >> ~/.bashrc echo "printf \"\n\x1b[31m \x1b[1m👉 Type: \\\`docker compose up\\\` to run the project. 👈\n\n\"" >> ~/.bashrc - -nohup bash -c "cd /wilco-agent && node agent.js &" >> /tmp/agent.log 2>&1 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/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/public/.keep b/.framework/node/backend/public/.keep deleted file mode 100644 index e69de29..0000000 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/start.sh b/.framework/node/backend/start.sh deleted file mode 100755 index bca7355..0000000 --- a/.framework/node/backend/start.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -yarn start 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-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-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/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/.gitignore b/.framework/rails/backend/.gitignore deleted file mode 100644 index e8245b7..0000000 --- a/.framework/rails/backend/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -# See https://help.github.com/items/ignoring-files for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile '~/.gitignore_global' - -# Ignore bundler config. -/.bundle - -# Ignore the default SQLite database. -/db/*.sqlite3 -/db/*.sqlite3-journal - -# Ignore all logfiles and tempfiles. -/log/* -/tmp/* -!/log/.keep -!/tmp/.keep - -# Ignore uploaded files in development -/storage/* - -/node_modules -/yarn-error.log - -/public/assets -.byebug_history - -# Ignore master key for decrypting credentials and more. -/config/master.key diff --git a/.framework/rails/backend/.ruby-version b/.framework/rails/backend/.ruby-version deleted file mode 100644 index 460b6fd..0000000 --- a/.framework/rails/backend/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.5 \ No newline at end of file diff --git a/.framework/rails/backend/Dockerfile b/.framework/rails/backend/Dockerfile deleted file mode 100644 index b9d3ef3..0000000 --- a/.framework/rails/backend/Dockerfile +++ /dev/null @@ -1 +0,0 @@ -FROM public.ecr.aws/v0a2l7y2/wilco/anythink-backend-rails:latest diff --git a/.framework/rails/backend/Dockerfile.aws b/.framework/rails/backend/Dockerfile.aws deleted file mode 100644 index 18fe3bb..0000000 --- a/.framework/rails/backend/Dockerfile.aws +++ /dev/null @@ -1,12 +0,0 @@ -FROM ruby:2.7.5 - -RUN apt-get update -qq && apt-get install -y build-essential nodejs - -WORKDIR /usr/src -COPY backend ./backend -COPY .wilco ./.wilco - -# Pre-install gems -WORKDIR /usr/src/backend -RUN bundle install - diff --git a/.framework/rails/backend/Gemfile b/.framework/rails/backend/Gemfile deleted file mode 100644 index 2eca1e4..0000000 --- a/.framework/rails/backend/Gemfile +++ /dev/null @@ -1,69 +0,0 @@ -source 'https://rubygems.org' -git_source(:github) { |repo| "https://github.com/#{repo}.git" } - -ruby '2.7.5' - -# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 6.1.0' -# Use Puma as the app server -gem 'puma', '~> 3.11' - -# Faraday -gem 'faraday' - -# Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '>= 1.3.0' -# See https://github.com/rails/execjs#readme for more supported runtimes -# gem 'mini_racer', platforms: :ruby - -# Use CoffeeScript for .coffee assets and views -gem 'coffee-rails', '~> 4.2' -# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks -gem 'turbolinks', '~> 5' -# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder', '~> 2.5' -# Use Redis adapter to run Action Cable in production -# gem 'redis', '~> 4.0' -# Use ActiveModel has_secure_password -# gem 'bcrypt', '~> 3.1.7' - -# Use ActiveStorage variant -# gem 'mini_magick', '~> 4.8' - -# Use Capistrano for deployment -# gem 'capistrano-rails', group: :development - -gem 'devise' -gem 'rack-cors' -gem 'acts-as-taggable-on', '~> 8.1.0' -gem 'jwt' -gem "acts_as_follower", github: "tcocca/acts_as_follower" -gem 'pg' - -# Reduces boot times through caching; required in config/boot.rb -gem 'bootsnap', '>= 1.1.0', require: false - -group :development, :test do - # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] -end - -group :development do - # Access an interactive console on exception pages or by calling 'console' anywhere in the code. - gem 'web-console', '>= 3.3.0' - gem 'listen', '>= 3.0.5', '< 3.2' - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' - gem 'spring-watcher-listen', '~> 2.0.0' -end - -group :test do - # Adds support for Capybara system testing and selenium driver - gem 'capybara', '>= 2.15', '< 4.0' - gem 'selenium-webdriver' - # Easy installation and use of chromedriver to run system tests with Chrome - gem 'chromedriver-helper' -end - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] diff --git a/.framework/rails/backend/Gemfile.lock b/.framework/rails/backend/Gemfile.lock deleted file mode 100644 index 9e838c7..0000000 --- a/.framework/rails/backend/Gemfile.lock +++ /dev/null @@ -1,258 +0,0 @@ -GIT - remote: https://github.com/tcocca/acts_as_follower.git - revision: c5ac7b9601c4af01eb4d9112330b27be4d694ecc - specs: - acts_as_follower (0.2.1) - activerecord (>= 4.0) - -GEM - remote: https://rubygems.org/ - specs: - actioncable (6.1.4.4) - actionpack (= 6.1.4.4) - activesupport (= 6.1.4.4) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - actionmailbox (6.1.4.4) - actionpack (= 6.1.4.4) - activejob (= 6.1.4.4) - activerecord (= 6.1.4.4) - activestorage (= 6.1.4.4) - activesupport (= 6.1.4.4) - mail (>= 2.7.1) - actionmailer (6.1.4.4) - actionpack (= 6.1.4.4) - actionview (= 6.1.4.4) - activejob (= 6.1.4.4) - activesupport (= 6.1.4.4) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (6.1.4.4) - actionview (= 6.1.4.4) - activesupport (= 6.1.4.4) - rack (~> 2.0, >= 2.0.9) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.4.4) - actionpack (= 6.1.4.4) - activerecord (= 6.1.4.4) - activestorage (= 6.1.4.4) - activesupport (= 6.1.4.4) - nokogiri (>= 1.8.5) - actionview (6.1.4.4) - activesupport (= 6.1.4.4) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.4.4) - activesupport (= 6.1.4.4) - globalid (>= 0.3.6) - activemodel (6.1.4.4) - activesupport (= 6.1.4.4) - activerecord (6.1.4.4) - activemodel (= 6.1.4.4) - activesupport (= 6.1.4.4) - activestorage (6.1.4.4) - actionpack (= 6.1.4.4) - activejob (= 6.1.4.4) - activerecord (= 6.1.4.4) - activesupport (= 6.1.4.4) - marcel (~> 1.0.0) - mini_mime (>= 1.1.0) - activesupport (6.1.4.4) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - acts-as-taggable-on (8.1.0) - activerecord (>= 5.0, < 6.2) - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) - archive-zip (0.12.0) - io-like (~> 0.3.0) - bcrypt (3.1.16) - bindex (0.8.1) - bootsnap (1.7.5) - msgpack (~> 1.0) - builder (3.2.4) - byebug (11.1.3) - capybara (3.35.3) - addressable - mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (>= 1.5, < 3.0) - xpath (~> 3.2) - childprocess (3.0.0) - chromedriver-helper (2.1.1) - archive-zip (~> 0.10) - nokogiri (~> 1.8) - coffee-rails (4.2.2) - coffee-script (>= 2.2.0) - railties (>= 4.0.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) - concurrent-ruby (1.1.9) - crass (1.0.6) - devise (4.8.1) - bcrypt (~> 3.0) - orm_adapter (~> 0.1) - railties (>= 4.1.0) - responders - warden (~> 1.2.3) - erubi (1.10.0) - execjs (2.7.0) - faraday (2.1.0) - faraday-net_http (~> 2.0) - ruby2_keywords (>= 0.0.4) - faraday-net_http (2.0.1) - ffi (1.15.0) - globalid (1.0.0) - activesupport (>= 5.0) - i18n (1.8.11) - concurrent-ruby (~> 1.0) - io-like (0.3.1) - jbuilder (2.11.2) - activesupport (>= 5.0.0) - jwt (1.5.6) - listen (3.1.5) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - ruby_dep (~> 1.2) - loofah (2.13.0) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) - mini_mime (>= 0.1.1) - marcel (1.0.2) - method_source (1.0.0) - mini_mime (1.1.0) - mini_portile2 (2.6.1) - minitest (5.15.0) - msgpack (1.4.2) - nio4r (2.5.8) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) - racc (~> 1.4) - orm_adapter (0.5.0) - pg (1.2.3) - public_suffix (4.0.6) - puma (3.12.6) - racc (1.6.0) - rack (2.2.3) - rack-cors (1.1.1) - rack (>= 2.0.0) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (6.1.4.4) - actioncable (= 6.1.4.4) - actionmailbox (= 6.1.4.4) - actionmailer (= 6.1.4.4) - actionpack (= 6.1.4.4) - actiontext (= 6.1.4.4) - actionview (= 6.1.4.4) - activejob (= 6.1.4.4) - activemodel (= 6.1.4.4) - activerecord (= 6.1.4.4) - activestorage (= 6.1.4.4) - activesupport (= 6.1.4.4) - bundler (>= 1.15.0) - railties (= 6.1.4.4) - sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.4.2) - loofah (~> 2.3) - railties (6.1.4.4) - actionpack (= 6.1.4.4) - activesupport (= 6.1.4.4) - method_source - rake (>= 0.13) - thor (~> 1.0) - rake (13.0.6) - rb-fsevent (0.10.4) - rb-inotify (0.10.1) - ffi (~> 1.0) - regexp_parser (2.1.1) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) - ruby2_keywords (0.0.5) - ruby_dep (1.5.0) - rubyzip (2.3.0) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) - spring (2.1.1) - spring-watcher-listen (2.0.1) - listen (>= 2.7, < 4.0) - spring (>= 1.2, < 3.0) - sprockets (4.0.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - sprockets (>= 3.0.0) - thor (1.1.0) - turbolinks (5.2.1) - turbolinks-source (~> 5.2) - turbolinks-source (5.2.0) - tzinfo (2.0.4) - concurrent-ruby (~> 1.0) - uglifier (4.2.0) - execjs (>= 0.3.0, < 3) - warden (1.2.9) - rack (>= 2.0.9) - web-console (4.2.0) - actionview (>= 6.0.0) - activemodel (>= 6.0.0) - bindex (>= 0.4.0) - railties (>= 6.0.0) - websocket-driver (0.7.5) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) - zeitwerk (2.5.2) - -PLATFORMS - ruby - -DEPENDENCIES - acts-as-taggable-on (~> 8.1.0) - acts_as_follower! - bootsnap (>= 1.1.0) - byebug - capybara (>= 2.15, < 4.0) - chromedriver-helper - coffee-rails (~> 4.2) - devise - faraday - jbuilder (~> 2.5) - jwt - listen (>= 3.0.5, < 3.2) - pg - puma (~> 3.11) - rack-cors - rails (~> 6.1.0) - selenium-webdriver - spring - spring-watcher-listen (~> 2.0.0) - turbolinks (~> 5) - tzinfo-data - uglifier (>= 1.3.0) - web-console (>= 3.3.0) - -RUBY VERSION - ruby 2.7.5p203 - -BUNDLED WITH - 2.1.4 diff --git a/.framework/rails/backend/README.md b/.framework/rails/backend/README.md deleted file mode 100644 index f056f30..0000000 --- a/.framework/rails/backend/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Anythink Market Backend - -The Anythink Market backend is Ruby web app written with [Ruby On Rails](https://rubyonrails.org/) - -## Dependencies - -- [acts_as_follower](https://github.com/tcocca/acts_as_follower) - For implementing followers/following -- [acts_as_taggable](https://github.com/mbleigh/acts-as-taggable-on) - For implementing tagging functionality -- [Devise](https://github.com/plataformatec/devise) - For implementing authentication -- [Jbuilder](https://github.com/rails/jbuilder) - Default JSON rendering gem that ships with Rails, used for making reusable templates for JSON output. -- [JWT](https://github.com/jwt/ruby-jwt) - For generating and validating JWTs for authentication - -## Folders - -- `app/models` - Contains the database models for the application where we can define methods, validations, queries, and relations to other models. -- `app/views` - Contains templates for generating the JSON output for the API -- `app/controllers` - Contains the controllers where requests are routed to their actions, where we find and manipulate our models and return them for the views to render. -- `config` - Contains configuration files for our Rails application and for our database, along with an `initializers` folder for scripts that get run on boot. -- `db` - Contains the migrations needed to create our database schema. diff --git a/.framework/rails/backend/Rakefile b/.framework/rails/backend/Rakefile deleted file mode 100644 index e85f913..0000000 --- a/.framework/rails/backend/Rakefile +++ /dev/null @@ -1,6 +0,0 @@ -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require_relative 'config/application' - -Rails.application.load_tasks diff --git a/.framework/rails/backend/app/assets/config/manifest.js b/.framework/rails/backend/app/assets/config/manifest.js deleted file mode 100644 index b16e53d..0000000 --- a/.framework/rails/backend/app/assets/config/manifest.js +++ /dev/null @@ -1,3 +0,0 @@ -//= link_tree ../images -//= link_directory ../javascripts .js -//= link_directory ../stylesheets .css diff --git a/.framework/rails/backend/app/assets/images/.keep b/.framework/rails/backend/app/assets/images/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/app/assets/javascripts/.keep b/.framework/rails/backend/app/assets/javascripts/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/app/assets/stylesheets/.keep b/.framework/rails/backend/app/assets/stylesheets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/app/channels/application_cable/channel.rb b/.framework/rails/backend/app/channels/application_cable/channel.rb deleted file mode 100644 index d672697..0000000 --- a/.framework/rails/backend/app/channels/application_cable/channel.rb +++ /dev/null @@ -1,4 +0,0 @@ -module ApplicationCable - class Channel < ActionCable::Channel::Base - end -end diff --git a/.framework/rails/backend/app/channels/application_cable/connection.rb b/.framework/rails/backend/app/channels/application_cable/connection.rb deleted file mode 100644 index 0ff5442..0000000 --- a/.framework/rails/backend/app/channels/application_cable/connection.rb +++ /dev/null @@ -1,4 +0,0 @@ -module ApplicationCable - class Connection < ActionCable::Connection::Base - end -end diff --git a/.framework/rails/backend/app/controllers/application_controller.rb b/.framework/rails/backend/app/controllers/application_controller.rb deleted file mode 100644 index c45cfd2..0000000 --- a/.framework/rails/backend/app/controllers/application_controller.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -class ApplicationController < ActionController::API - include ActionController::HttpAuthentication::Token::ControllerMethods - - before_action :configure_permitted_parameters, if: :devise_controller? - before_action :authenticate_user - - def root - render plain: "API server is up and running, please use the frontend app to interact with the system" - end - - def health - render plain: 'OK' - end - - private - - def configure_permitted_parameters - devise_parameter_sanitizer.permit(:sign_up, keys: [:username]) - end - - def authenticate_user - return if request.headers['Authorization'].blank? - - authenticate_or_request_with_http_token do |token| - begin - jwt_payload = JWT.decode(token, Rails.application.secrets.secret_key_base).first - - @current_user_id = jwt_payload['id'] - rescue JWT::ExpiredSignature, JWT::VerificationError, JWT::DecodeError - head :unauthorized - end - end - end - - def authenticate_user!(_options = {}) - head :unauthorized unless signed_in? - end - - def current_user - @current_user ||= super || User.find(@current_user_id) - end - - def signed_in? - @current_user_id.present? - end -end diff --git a/.framework/rails/backend/app/controllers/comments_controller.rb b/.framework/rails/backend/app/controllers/comments_controller.rb deleted file mode 100644 index 6bd39e7..0000000 --- a/.framework/rails/backend/app/controllers/comments_controller.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -class CommentsController < ApplicationController - before_action :authenticate_user!, except: [:index] - before_action :find_item! - - def index - @comments = @item.comments.order(created_at: :desc) - end - - def create - @comment = @item.comments.new(comment_params) - @comment.user = current_user - - render json: { errors: @comment.errors }, status: :unprocessable_entity unless @comment.save - end - - def destroy - @comment = @item.comments.find(params[:id]) - - @comment.destroy - render json: {} - end - - private - - def comment_params - params.require(:comment).permit(:body) - end - - def find_item! - @item = Item.find_by!(slug: params[:item_slug]) - end -end diff --git a/.framework/rails/backend/app/controllers/concerns/.keep b/.framework/rails/backend/app/controllers/concerns/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/app/controllers/favorites_controller.rb b/.framework/rails/backend/app/controllers/favorites_controller.rb deleted file mode 100644 index 191d138..0000000 --- a/.framework/rails/backend/app/controllers/favorites_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -class FavoritesController < ApplicationController - before_action :authenticate_user! - before_action :find_item! - - def create - current_user.favorite(@item) - - render 'items/show' - end - - def destroy - current_user.unfavorite(@item) - - render 'items/show' - end - - private - - def find_item! - @item = Item.find_by!(slug: params[:item_slug]) - end -end diff --git a/.framework/rails/backend/app/controllers/follows_controller.rb b/.framework/rails/backend/app/controllers/follows_controller.rb deleted file mode 100644 index fa6f674..0000000 --- a/.framework/rails/backend/app/controllers/follows_controller.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -class FollowsController < ApplicationController - before_action :authenticate_user! - - def create - @user = User.find_by!(username: params[:profile_username]) - - current_user.follow(@user) if current_user.id != @user.id - - render 'profiles/show' - end - - def destroy - @user = User.find_by!(username: params[:profile_username]) - - current_user.stop_following(@user) if current_user.id != @user.id - - render 'profiles/show' - end -end diff --git a/.framework/rails/backend/app/controllers/items_controller.rb b/.framework/rails/backend/app/controllers/items_controller.rb deleted file mode 100644 index 0e92499..0000000 --- a/.framework/rails/backend/app/controllers/items_controller.rb +++ /dev/null @@ -1,98 +0,0 @@ -# frozen_string_literal: true -require_relative "../../lib/event" -include Event - -class ItemsController < ApplicationController - before_action :authenticate_user!, except: %i[index show] - - def index - @items = Item.includes(:tags) - - @items = @items.tagged_with(params[:tag]) if params[:tag].present? - @items = @items.sellered_by(params[:seller]) if params[:seller].present? - @items = @items.favorited_by(params[:favorited]) if params[:favorited].present? - - @items_count = @items.count - - @items = @items.order(created_at: :desc).offset(params[:offset] || 0).limit(params[:limit] || 100) - - render json: { - items: @items.map { |item| - { - title: item.title, - slug: item.slug, - description: item.description, - image: item.image, - tagList: item.tags.map(&:name), - createdAt: item.created_at, - updatedAt: item.updated_at, - seller: { - username: item.user.username, - bio: item.user.bio, - image: item.user.image || 'https://static.productionready.io/images/smiley-cyrus.jpg', - following: signed_in? ? current_user.following?(item.user) : false, - }, - favorited: signed_in? ? current_user.favorited?(item) : false, - favoritesCount: item.favorites_count || 0 - } - }, - items_count: @items_count - } - end - - def feed - @items = Item.includes(:user).where(user: current_user.following_users) - - @items_count = @items.count - - @items = @items.order(created_at: :asc).offset(params[:offset] || 0).limit(params[:limit] || 20) - - render :index - end - - def create - @item = Item.new(item_params) - @item.user = current_user - - if @item.save - sendEvent("item_created", { item: item_params }) - render :show - else - render json: { errors: @item.errors }, status: :unprocessable_entity - end - end - - def show - @item = Item.find_by!(slug: params[:slug]) - end - - def update - @item = Item.find_by!(slug: params[:slug]) - - if @item.user_id == @current_user_id - @item.update(item_params) - - render :show - else - render json: { errors: { item: ['not owned by user'] } }, status: :forbidden - end - end - - def destroy - @item = Item.find_by!(slug: params[:slug]) - - if @item.user_id == @current_user_id - @item.destroy - - render json: {} - else - render json: { errors: { item: ['not owned by user'] } }, status: :forbidden - end - end - - private - - def item_params - params.require(:item).permit(:title, :description, :image, tag_list: []) - end -end diff --git a/.framework/rails/backend/app/controllers/ping_controller.rb b/.framework/rails/backend/app/controllers/ping_controller.rb deleted file mode 100644 index 4d72c28..0000000 --- a/.framework/rails/backend/app/controllers/ping_controller.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true -include Faraday -require_relative "../../lib/event" -include Event - -class PingController < ApplicationController - def index - response = sendEvent("ping", nil) - render json: response.body - end -end diff --git a/.framework/rails/backend/app/controllers/profiles_controller.rb b/.framework/rails/backend/app/controllers/profiles_controller.rb deleted file mode 100644 index 95898c8..0000000 --- a/.framework/rails/backend/app/controllers/profiles_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class ProfilesController < ApplicationController - def show - @user = User.find_by(username: params[:username]) - end -end diff --git a/.framework/rails/backend/app/controllers/registrations_controller.rb b/.framework/rails/backend/app/controllers/registrations_controller.rb deleted file mode 100644 index 9a8f8e4..0000000 --- a/.framework/rails/backend/app/controllers/registrations_controller.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -require_relative "../../lib/event" -include Event - -class RegistrationsController < Devise::RegistrationsController - def create - super - - if @user.persisted? - sendEvent("user_created", { username: @user.username }) - end - end -end diff --git a/.framework/rails/backend/app/controllers/sessions_controller.rb b/.framework/rails/backend/app/controllers/sessions_controller.rb deleted file mode 100644 index f2cdf07..0000000 --- a/.framework/rails/backend/app/controllers/sessions_controller.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -class SessionsController < Devise::SessionsController - def create - user = User.find_by(email: sign_in_params[:email]) - - if user && user.valid_password?(sign_in_params[:password]) - @current_user = user - else - render json: { errors: { 'email or password' => ['is invalid'] } }, status: :unprocessable_entity - end - end -end diff --git a/.framework/rails/backend/app/controllers/tags_controller.rb b/.framework/rails/backend/app/controllers/tags_controller.rb deleted file mode 100644 index 7d73a96..0000000 --- a/.framework/rails/backend/app/controllers/tags_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class TagsController < ApplicationController - def index - render json: { tags: Item.tag_counts.most_used.map(&:name) } - end -end diff --git a/.framework/rails/backend/app/controllers/users_controller.rb b/.framework/rails/backend/app/controllers/users_controller.rb deleted file mode 100644 index c98f170..0000000 --- a/.framework/rails/backend/app/controllers/users_controller.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -class UsersController < ApplicationController - before_action :authenticate_user! - - def show; end - - def update - if current_user.update(user_params) - render :show - else - render json: { errors: current_user.errors }, status: :unprocessable_entity - end - end - - private - - def user_params - params.require(:user).permit(:username, :email, :password, :bio, :image) - end -end diff --git a/.framework/rails/backend/app/helpers/application_helper.rb b/.framework/rails/backend/app/helpers/application_helper.rb deleted file mode 100644 index de6be79..0000000 --- a/.framework/rails/backend/app/helpers/application_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ApplicationHelper -end diff --git a/.framework/rails/backend/app/jobs/application_job.rb b/.framework/rails/backend/app/jobs/application_job.rb deleted file mode 100644 index a009ace..0000000 --- a/.framework/rails/backend/app/jobs/application_job.rb +++ /dev/null @@ -1,2 +0,0 @@ -class ApplicationJob < ActiveJob::Base -end diff --git a/.framework/rails/backend/app/mailers/application_mailer.rb b/.framework/rails/backend/app/mailers/application_mailer.rb deleted file mode 100644 index 286b223..0000000 --- a/.framework/rails/backend/app/mailers/application_mailer.rb +++ /dev/null @@ -1,4 +0,0 @@ -class ApplicationMailer < ActionMailer::Base - default from: 'from@example.com' - layout 'mailer' -end diff --git a/.framework/rails/backend/app/models/application_record.rb b/.framework/rails/backend/app/models/application_record.rb deleted file mode 100644 index 10a4cba..0000000 --- a/.framework/rails/backend/app/models/application_record.rb +++ /dev/null @@ -1,3 +0,0 @@ -class ApplicationRecord < ActiveRecord::Base - self.abstract_class = true -end diff --git a/.framework/rails/backend/app/models/comment.rb b/.framework/rails/backend/app/models/comment.rb deleted file mode 100644 index 75d76cf..0000000 --- a/.framework/rails/backend/app/models/comment.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -class Comment < ApplicationRecord - belongs_to :user - belongs_to :item - - validates :body, presence: true, allow_blank: false -end diff --git a/.framework/rails/backend/app/models/concerns/.keep b/.framework/rails/backend/app/models/concerns/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/app/models/favorite.rb b/.framework/rails/backend/app/models/favorite.rb deleted file mode 100644 index afc2a4c..0000000 --- a/.framework/rails/backend/app/models/favorite.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -class Favorite < ApplicationRecord - belongs_to :user - belongs_to :item, counter_cache: true -end diff --git a/.framework/rails/backend/app/models/follow.rb b/.framework/rails/backend/app/models/follow.rb deleted file mode 100644 index 0746982..0000000 --- a/.framework/rails/backend/app/models/follow.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -class Follow < ApplicationRecord - extend ActsAsFollower::FollowerLib - extend ActsAsFollower::FollowScopes - - # NOTE: Follows belong to the "followable" interface, and also to followers - belongs_to :followable, polymorphic: true - belongs_to :follower, polymorphic: true - - def block! - update_attribute(:blocked, true) - end -end diff --git a/.framework/rails/backend/app/models/item.rb b/.framework/rails/backend/app/models/item.rb deleted file mode 100644 index b03d86e..0000000 --- a/.framework/rails/backend/app/models/item.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -class Item < ApplicationRecord - belongs_to :user - has_many :favorites, dependent: :destroy - has_many :comments, dependent: :destroy - - scope :sellered_by, ->(username) { where(user: User.where(username: username)) } - scope :favorited_by, ->(username) { joins(:favorites).where(favorites: { user: User.where(username: username) }) } - - acts_as_taggable - - validates :title, presence: true, allow_blank: false - validates :description, presence: true, allow_blank: false - validates :slug, uniqueness: true, exclusion: { in: ['feed'] } - - before_validation do - self.slug ||= "#{title.to_s.parameterize}-#{rand(36**6).to_s(36)}" - end -end diff --git a/.framework/rails/backend/app/models/user.rb b/.framework/rails/backend/app/models/user.rb deleted file mode 100644 index 1011b20..0000000 --- a/.framework/rails/backend/app/models/user.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -class User < ApplicationRecord - # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable - devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable - - has_many :items, dependent: :destroy - has_many :favorites, dependent: :destroy - has_many :comments, dependent: :destroy - - acts_as_follower - acts_as_followable - - validates :username, uniqueness: { case_sensitive: true }, - format: { with: /\A[a-zA-Z0-9]+\z/ }, - presence: true, - allow_blank: false - - def generate_jwt - JWT.encode({ id: id, - exp: 60.days.from_now.to_i }, - Rails.application.secrets.secret_key_base) - end - - def favorite(item) - favorites.find_or_create_by(item: item) - end - - def unfavorite(item) - favorites.where(item: item).destroy_all - - item.reload - end - - def favorited?(item) - favorites.find_by(item_id: item.id).present? - end -end diff --git a/.framework/rails/backend/app/views/comments/_comment.json.jbuilder b/.framework/rails/backend/app/views/comments/_comment.json.jbuilder deleted file mode 100644 index 9fdf442..0000000 --- a/.framework/rails/backend/app/views/comments/_comment.json.jbuilder +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -json.call(comment, :id, :body) -json.createdAt comment.created_at -json.updatedAt comment.updated_at -json.seller comment.user, partial: 'profiles/profile', as: :user diff --git a/.framework/rails/backend/app/views/comments/create.json.jbuilder b/.framework/rails/backend/app/views/comments/create.json.jbuilder deleted file mode 100644 index e9773ab..0000000 --- a/.framework/rails/backend/app/views/comments/create.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.comment do |json| - json.partial! 'comments/comment', comment: @comment -end diff --git a/.framework/rails/backend/app/views/comments/index.json.jbuilder b/.framework/rails/backend/app/views/comments/index.json.jbuilder deleted file mode 100644 index 502bea2..0000000 --- a/.framework/rails/backend/app/views/comments/index.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.comments do |json| - json.array! @comments, partial: 'comments/comment', as: :comment -end diff --git a/.framework/rails/backend/app/views/devise/registrations/create.json.jbuilder b/.framework/rails/backend/app/views/devise/registrations/create.json.jbuilder deleted file mode 100644 index 60f1da9..0000000 --- a/.framework/rails/backend/app/views/devise/registrations/create.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.user do |json| - json.partial! 'users/user', user: current_user -end diff --git a/.framework/rails/backend/app/views/devise/sessions/create.json.jbuilder b/.framework/rails/backend/app/views/devise/sessions/create.json.jbuilder deleted file mode 100644 index 60f1da9..0000000 --- a/.framework/rails/backend/app/views/devise/sessions/create.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.user do |json| - json.partial! 'users/user', user: current_user -end diff --git a/.framework/rails/backend/app/views/items/_item.json.jbuilder b/.framework/rails/backend/app/views/items/_item.json.jbuilder deleted file mode 100644 index 183b449..0000000 --- a/.framework/rails/backend/app/views/items/_item.json.jbuilder +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -json.call(item, :title, :slug, :description, :image) -json.createdAt item.created_at -json.updatedAt item.updated_at -json.tagList item.tag_list -json.seller item.user, partial: 'profiles/profile', as: :user -json.favorited signed_in? ? current_user.favorited?(item) : false -json.favoritesCount item.favorites_count || 0 diff --git a/.framework/rails/backend/app/views/items/index.json.jbuilder b/.framework/rails/backend/app/views/items/index.json.jbuilder deleted file mode 100644 index 3d644dd..0000000 --- a/.framework/rails/backend/app/views/items/index.json.jbuilder +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -json.items do |json| - json.array! @items, partial: 'items/item', as: :item -end - -json.items_count @items_count diff --git a/.framework/rails/backend/app/views/items/show.json.jbuilder b/.framework/rails/backend/app/views/items/show.json.jbuilder deleted file mode 100644 index 2d84564..0000000 --- a/.framework/rails/backend/app/views/items/show.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.item do |json| - json.partial! 'items/item', item: @item -end diff --git a/.framework/rails/backend/app/views/profiles/_profile.json.jbuilder b/.framework/rails/backend/app/views/profiles/_profile.json.jbuilder deleted file mode 100644 index ded3482..0000000 --- a/.framework/rails/backend/app/views/profiles/_profile.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.call(user, :username, :bio) -json.image user.image || 'https://static.productionready.io/images/smiley-cyrus.jpg' -json.following signed_in? ? current_user.following?(user) : false diff --git a/.framework/rails/backend/app/views/profiles/show.json.jbuilder b/.framework/rails/backend/app/views/profiles/show.json.jbuilder deleted file mode 100644 index 887ba8e..0000000 --- a/.framework/rails/backend/app/views/profiles/show.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.profile do |json| - json.partial! 'profiles/profile', user: @user -end diff --git a/.framework/rails/backend/app/views/users/_user.json.jbuilder b/.framework/rails/backend/app/views/users/_user.json.jbuilder deleted file mode 100644 index a7ff346..0000000 --- a/.framework/rails/backend/app/views/users/_user.json.jbuilder +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true - -json.call(user, :id, :email, :username, :bio, :image) -json.token user.generate_jwt diff --git a/.framework/rails/backend/app/views/users/show.json.jbuilder b/.framework/rails/backend/app/views/users/show.json.jbuilder deleted file mode 100644 index 60f1da9..0000000 --- a/.framework/rails/backend/app/views/users/show.json.jbuilder +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -json.user do |json| - json.partial! 'users/user', user: current_user -end diff --git a/.framework/rails/backend/bin/bundle b/.framework/rails/backend/bin/bundle deleted file mode 100755 index f19acf5..0000000 --- a/.framework/rails/backend/bin/bundle +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -load Gem.bin_path('bundler', 'bundle') diff --git a/.framework/rails/backend/bin/heroku_release.sh b/.framework/rails/backend/bin/heroku_release.sh deleted file mode 100755 index 35fae48..0000000 --- a/.framework/rails/backend/bin/heroku_release.sh +++ /dev/null @@ -1,25 +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 - -schema_version=$(bin/rails db:version | { grep "^Current version: [0-9]\\+$" || true; } | tr -s ' ' | cut -d ' ' -f3) - -if [ -z "$schema_version" ]; then - printf "\n⏳${YELLOW} [Release Phase]: Seeding db from scratch.${NO_COLOR}\n" - bin/rails db:init - bin/rails db:migrate - bin/rails db:seed -elif [ "$schema_version" -eq "0" ]; then - printf "\n⏳${YELLOW} [Release Phase]: Loading the database schema.${NO_COLOR}\n" - bin/rails db:schema:load - bin/rails db:seed -fi - -printf "\n🎉${GREEN} [Release Phase]: Database is up to date.${NO_COLOR}\n" \ No newline at end of file diff --git a/.framework/rails/backend/bin/rails b/.framework/rails/backend/bin/rails deleted file mode 100755 index 5badb2f..0000000 --- a/.framework/rails/backend/bin/rails +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' diff --git a/.framework/rails/backend/bin/rake b/.framework/rails/backend/bin/rake deleted file mode 100755 index d87d5f5..0000000 --- a/.framework/rails/backend/bin/rake +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -require_relative '../config/boot' -require 'rake' -Rake.application.run diff --git a/.framework/rails/backend/bin/setup b/.framework/rails/backend/bin/setup deleted file mode 100755 index 94fd4d7..0000000 --- a/.framework/rails/backend/bin/setup +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env ruby -require 'fileutils' -include FileUtils - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a starting point to setup your application. - # Add necessary setup steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - # Install JavaScript dependencies if using Yarn - # system('bin/yarn') - - # puts "\n== Copying sample files ==" - # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' - # end - - puts "\n== Preparing database ==" - system! 'bin/rails db:setup' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end diff --git a/.framework/rails/backend/bin/spring b/.framework/rails/backend/bin/spring deleted file mode 100755 index d89ee49..0000000 --- a/.framework/rails/backend/bin/spring +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby - -# This file loads Spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. - -unless defined?(Spring) - require 'rubygems' - require 'bundler' - - lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) - spring = lockfile.specs.detect { |spec| spec.name == 'spring' } - if spring - Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path - gem 'spring', spring.version - require 'spring/binstub' - end -end diff --git a/.framework/rails/backend/bin/update b/.framework/rails/backend/bin/update deleted file mode 100755 index 58bfaed..0000000 --- a/.framework/rails/backend/bin/update +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env ruby -require 'fileutils' -include FileUtils - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a way to update your development environment automatically. - # Add necessary update steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - # Install JavaScript dependencies if using Yarn - # system('bin/yarn') - - puts "\n== Updating database ==" - system! 'bin/rails db:migrate' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end diff --git a/.framework/rails/backend/bin/yarn b/.framework/rails/backend/bin/yarn deleted file mode 100755 index 460dd56..0000000 --- a/.framework/rails/backend/bin/yarn +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env ruby -APP_ROOT = File.expand_path('..', __dir__) -Dir.chdir(APP_ROOT) do - begin - exec "yarnpkg", *ARGV - rescue Errno::ENOENT - $stderr.puts "Yarn executable was not detected in the system." - $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" - exit 1 - end -end diff --git a/.framework/rails/backend/config.ru b/.framework/rails/backend/config.ru deleted file mode 100644 index f7ba0b5..0000000 --- a/.framework/rails/backend/config.ru +++ /dev/null @@ -1,5 +0,0 @@ -# This file is used by Rack-based servers to start the application. - -require_relative 'config/environment' - -run Rails.application diff --git a/.framework/rails/backend/config/application.rb b/.framework/rails/backend/config/application.rb deleted file mode 100644 index 75f6674..0000000 --- a/.framework/rails/backend/config/application.rb +++ /dev/null @@ -1,22 +0,0 @@ -require_relative 'boot' - -require 'rails/all' - -# Require the gems listed in Gemfile, including any gems -# you've limited to :test, :development, or :production. -Bundler.require(*Rails.groups) - -module AnythinkMarket - class Application < Rails::Application - # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.2 - config.api_only = true - - # Allow all hosts - config.hosts = nil - - config.to_prepare do - DeviseController.respond_to :html, :json - end - end -end diff --git a/.framework/rails/backend/config/boot.rb b/.framework/rails/backend/config/boot.rb deleted file mode 100644 index b9e460c..0000000 --- a/.framework/rails/backend/config/boot.rb +++ /dev/null @@ -1,4 +0,0 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) - -require 'bundler/setup' # Set up gems listed in the Gemfile. -require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/.framework/rails/backend/config/cable.yml b/.framework/rails/backend/config/cable.yml deleted file mode 100644 index 2dfc57c..0000000 --- a/.framework/rails/backend/config/cable.yml +++ /dev/null @@ -1,10 +0,0 @@ -development: - adapter: async - -test: - adapter: async - -production: - adapter: redis - url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> - channel_prefix: AnythinkMarket_production diff --git a/.framework/rails/backend/config/credentials.yml.enc b/.framework/rails/backend/config/credentials.yml.enc deleted file mode 100644 index 020476e..0000000 --- a/.framework/rails/backend/config/credentials.yml.enc +++ /dev/null @@ -1 +0,0 @@ -QAFQjUBh2bXf1g8q1zIUvSj39taFJML8JgK9OcL4vFBXG+N4F3lLlrG8N8Fjdzw34be/TgFRlrk5VkTYaf7jdcmL1OeFPK/Ny4/8In/PKg3LK319iY3ths+5rhBQzJqFxicmOg6VI/E6H1h3evxrKFEdcegN9F+Zf7U9bBmHgiWbD7FQemox/21EzFeyq+z3IiVlTB4OlEg9WT5GF5UPkeh2vT7LfCPLxb/yH9UntxcrJvkNzW3bgqXUhKzuT6dClpTpieHGJIEcQNGfMOhtu58SLX86/utPKBY+olX3cY7bwlReDYGxZECCruf5IL+UFg8bQM99TQZwwvlGpi+4HDHD4Rmkff4VGSgxNAOT7Uk4OiobK7mHbR+Wj78/48TEAGkGTr40AxDg4NVLegtLx81TZEejkH5tp1XF--BCh73RGeAwVePiSo--s/TsxgL/nFnzGqAYtDOVxA== \ No newline at end of file diff --git a/.framework/rails/backend/config/database.yml b/.framework/rails/backend/config/database.yml deleted file mode 100644 index ce77d59..0000000 --- a/.framework/rails/backend/config/database.yml +++ /dev/null @@ -1,21 +0,0 @@ -default: &default - adapter: postgresql - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - timeout: 5000 - url: <%= ENV['DATABASE_URL'] %> - -development: - <<: *default - encoding: unicode - pool: 5 - -test: - <<: *default - -production: - <<: *default - adapter: postgresql - encoding: unicode - pool: 5 - prepared_statements: false - advisory_locks: false diff --git a/.framework/rails/backend/config/environment.rb b/.framework/rails/backend/config/environment.rb deleted file mode 100644 index 426333b..0000000 --- a/.framework/rails/backend/config/environment.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Load the Rails application. -require_relative 'application' - -# Initialize the Rails application. -Rails.application.initialize! diff --git a/.framework/rails/backend/config/environments/development.rb b/.framework/rails/backend/config/environments/development.rb deleted file mode 100644 index 7e6af8d..0000000 --- a/.framework/rails/backend/config/environments/development.rb +++ /dev/null @@ -1,63 +0,0 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development - # since you don't have to restart the web server when you make code changes. - config.cache_classes = false - - # Do not eager load code on boot. - config.eager_load = false - - # Show full error reports. - config.consider_all_requests_local = true - - # Enable/disable caching. By default caching is disabled. - # Run rails dev:cache to toggle caching. - if Rails.root.join('tmp', 'caching-dev.txt').exist? - config.action_controller.perform_caching = true - - config.cache_store = :memory_store - config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.to_i}" - } - else - config.action_controller.perform_caching = false - - config.cache_store = :null_store - end - - # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = :local - - # Don't care if the mailer can't send. - config.action_mailer.raise_delivery_errors = false - - config.action_mailer.perform_caching = false - - # Print deprecation notices to the Rails logger. - config.active_support.deprecation = :log - - # Raise an error on page load if there are pending migrations. - config.active_record.migration_error = :page_load - - # Highlight code that triggered database queries in logs. - config.active_record.verbose_query_logs = true - - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true - - # Suppress logger output for asset requests. - config.assets.quiet = true - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true - - # Use an evented file watcher to asynchronously detect changes in source code, - # routes, locales, etc. This feature depends on the listen gem. - config.file_watcher = ActiveSupport::EventedFileUpdateChecker - - config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } -end diff --git a/.framework/rails/backend/config/environments/production.rb b/.framework/rails/backend/config/environments/production.rb deleted file mode 100644 index a9103c9..0000000 --- a/.framework/rails/backend/config/environments/production.rb +++ /dev/null @@ -1,93 +0,0 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # Code is not reloaded between requests. - config.cache_classes = true - - # Eager load code on boot. This eager loads most of Rails and - # your application in memory, allowing both threaded web servers - # and those relying on copy on write to perform better. - # Rake tasks automatically ignore this option for performance. - config.eager_load = true - - # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false - config.action_controller.perform_caching = true - - # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] - # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). - # config.require_master_key = true - - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. - config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? - - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false - - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb - - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' - - # Specifies the header that your server uses for sending files. - # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - - # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = :local - - # Mount Action Cable outside main process or domain - # config.action_cable.mount_path = nil - # config.action_cable.url = 'wss://example.com/cable' - # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] - - # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true - - # Use the lowest log level to ensure availability of diagnostic information - # when problems arise. - config.log_level = :debug - - # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] - - # Use a different cache store in production. - # config.cache_store = :mem_cache_store - - # Use a real queuing backend for Active Job (and separate queues per environment) - # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "AnythinkMarket_#{Rails.env}" - - config.action_mailer.perform_caching = false - - # Ignore bad email addresses and do not raise email delivery errors. - # Set this to true and configure the email server for immediate delivery to raise delivery errors. - # config.action_mailer.raise_delivery_errors = false - - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation cannot be found). - config.i18n.fallbacks = true - - # Send deprecation notices to registered listeners. - config.active_support.deprecation = :notify - - # Use default logging formatter so that PID and timestamp are not suppressed. - config.log_formatter = ::Logger::Formatter.new - - # Use a different logger for distributed setups. - # require 'syslog/logger' - # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - end - - # Do not dump schema after migrations. - config.active_record.dump_schema_after_migration = false -end diff --git a/.framework/rails/backend/config/environments/test.rb b/.framework/rails/backend/config/environments/test.rb deleted file mode 100644 index 0a38fd3..0000000 --- a/.framework/rails/backend/config/environments/test.rb +++ /dev/null @@ -1,46 +0,0 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true - - # Do not eager load code on boot. This avoids loading your whole application - # just for the purpose of running a single test. If you are using a tool that - # preloads Rails for running tests, you may have to set it to true. - config.eager_load = false - - # Configure public file server for tests with Cache-Control for performance. - config.public_file_server.enabled = true - config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.to_i}" - } - - # Show full error reports and disable caching. - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false - - # Disable request forgery protection in test environment. - config.action_controller.allow_forgery_protection = false - - # Store uploaded files on the local file system in a temporary directory - config.active_storage.service = :test - - config.action_mailer.perform_caching = false - - # Tell Action Mailer not to deliver emails to the real world. - # The :test delivery method accumulates sent emails in the - # ActionMailer::Base.deliveries array. - config.action_mailer.delivery_method = :test - - # Print deprecation notices to the stderr. - config.active_support.deprecation = :stderr - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true -end diff --git a/.framework/rails/backend/config/initializers/application_controller_renderer.rb b/.framework/rails/backend/config/initializers/application_controller_renderer.rb deleted file mode 100644 index 89d2efa..0000000 --- a/.framework/rails/backend/config/initializers/application_controller_renderer.rb +++ /dev/null @@ -1,8 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# ActiveSupport::Reloader.to_prepare do -# ApplicationController.renderer.defaults.merge!( -# http_host: 'example.org', -# https: false -# ) -# end diff --git a/.framework/rails/backend/config/initializers/assets.rb b/.framework/rails/backend/config/initializers/assets.rb deleted file mode 100644 index 4b828e8..0000000 --- a/.framework/rails/backend/config/initializers/assets.rb +++ /dev/null @@ -1,14 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' - -# Add additional assets to the asset load path. -# Rails.application.config.assets.paths << Emoji.images_path -# Add Yarn node_modules folder to the asset load path. -Rails.application.config.assets.paths << Rails.root.join('node_modules') - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in the app/assets -# folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/.framework/rails/backend/config/initializers/backtrace_silencers.rb b/.framework/rails/backend/config/initializers/backtrace_silencers.rb deleted file mode 100644 index 59385cd..0000000 --- a/.framework/rails/backend/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/.framework/rails/backend/config/initializers/content_security_policy.rb b/.framework/rails/backend/config/initializers/content_security_policy.rb deleted file mode 100644 index d3bcaa5..0000000 --- a/.framework/rails/backend/config/initializers/content_security_policy.rb +++ /dev/null @@ -1,25 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Define an application-wide content security policy -# For further information see the following documentation -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - -# Rails.application.config.content_security_policy do |policy| -# policy.default_src :self, :https -# policy.font_src :self, :https, :data -# policy.img_src :self, :https, :data -# policy.object_src :none -# policy.script_src :self, :https -# policy.style_src :self, :https - -# # Specify URI for violation reports -# # policy.report_uri "/csp-violation-report-endpoint" -# end - -# If you are using UJS then enable automatic nonce generation -# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } - -# Report CSP violations to a specified URI -# For further information see the following documentation: -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only -# Rails.application.config.content_security_policy_report_only = true diff --git a/.framework/rails/backend/config/initializers/cookies_serializer.rb b/.framework/rails/backend/config/initializers/cookies_serializer.rb deleted file mode 100644 index 5a6a32d..0000000 --- a/.framework/rails/backend/config/initializers/cookies_serializer.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Specify a serializer for the signed and encrypted cookie jars. -# Valid options are :json, :marshal, and :hybrid. -Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/.framework/rails/backend/config/initializers/cors.rb b/.framework/rails/backend/config/initializers/cors.rb deleted file mode 100644 index b745aba..0000000 --- a/.framework/rails/backend/config/initializers/cors.rb +++ /dev/null @@ -1,9 +0,0 @@ -Rails.application.config.middleware.insert_before 0, Rack::Cors, debug: true, logger: (-> { Rails.logger }) do - allow do - origins '*' - - resource '*', - headers: :any, - methods: [:get, :post, :put, :patch, :delete, :options, :head] - end -end diff --git a/.framework/rails/backend/config/initializers/devise.rb b/.framework/rails/backend/config/initializers/devise.rb deleted file mode 100644 index 002356b..0000000 --- a/.framework/rails/backend/config/initializers/devise.rb +++ /dev/null @@ -1,311 +0,0 @@ -# frozen_string_literal: true - -# Assuming you have not yet modified this file, each configuration option below -# is set to its default value. Note that some are commented out while others -# are not: uncommented lines are intended to protect your configuration from -# breaking changes in upgrades (i.e., in the event that future versions of -# Devise change the default values for those options). -# -# Use this hook to configure devise mailer, warden hooks and so forth. -# Many of these configuration options can be set straight in your model. -Devise.setup do |config| - # The secret key used by Devise. Devise uses this key to generate - # random tokens. Changing this key will render invalid all existing - # confirmation, reset password and unlock tokens in the database. - # Devise will use the `secret_key_base` as its `secret_key` - # by default. You can change it below and use your own secret key. - # config.secret_key = 'eca6e8be56768ce1455d5a43892b0db1144c4015b2417aac99712a9f7df34677e212942a0c4e8f8768b6b9458e0b453774e0c2a9ac3f600b5e78842e725be180' - - # ==> Controller configuration - # Configure the parent class to the devise controllers. - # config.parent_controller = 'DeviseController' - - # ==> Mailer Configuration - # Configure the e-mail address which will be shown in Devise::Mailer, - # note that it will be overwritten if you use your own mailer class - # with default "from" parameter. - config.mailer_sender = 'hello@anythink.family' - - # Configure the class responsible to send e-mails. - # config.mailer = 'Devise::Mailer' - - # Configure the parent class responsible to send e-mails. - # config.parent_mailer = 'ActionMailer::Base' - - # ==> ORM configuration - # Load and configure the ORM. Supports :active_record (default) and - # :mongoid (bson_ext recommended) by default. Other ORMs may be - # available as additional gems. - require 'devise/orm/active_record' - - # ==> Configuration for any authentication mechanism - # Configure which keys are used when authenticating a user. The default is - # just :email. You can configure it to use [:username, :subdomain], so for - # authenticating a user, both parameters are required. Remember that those - # parameters are used only when authenticating and not when retrieving from - # session. If you need permissions, you should implement that in a before filter. - # You can also supply a hash where the value is a boolean determining whether - # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [:email] - - # Configure parameters from the request object used for authentication. Each entry - # given should be a request method and it will automatically be passed to the - # find_for_authentication method and considered in your model lookup. For instance, - # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. - # The same considerations mentioned for authentication_keys also apply to request_keys. - # config.request_keys = [] - - # Configure which authentication keys should be case-insensitive. - # These keys will be downcased upon creating or modifying a user and when used - # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [:email] - - # Configure which authentication keys should have whitespace stripped. - # These keys will have whitespace before and after removed upon creating or - # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [:email] - - # Tell if authentication through request.params is enabled. True by default. - # It can be set to an array that will enable params authentication only for the - # given strategies, for example, `config.params_authenticatable = [:database]` will - # enable it only for database (email + password) authentication. - # config.params_authenticatable = true - - # Tell if authentication through HTTP Auth is enabled. False by default. - # It can be set to an array that will enable http authentication only for the - # given strategies, for example, `config.http_authenticatable = [:database]` will - # enable it only for database authentication. - # For API-only applications to support authentication "out-of-the-box", you will likely want to - # enable this with :database unless you are using a custom strategy. - # The supported strategies are: - # :database = Support basic authentication with authentication key + password - # config.http_authenticatable = false - - # If 401 status code should be returned for AJAX requests. True by default. - # config.http_authenticatable_on_xhr = true - - # The realm used in Http Basic Authentication. 'Application' by default. - # config.http_authentication_realm = 'Application' - - # It will change confirmation, password recovery and other workflows - # to behave the same regardless if the e-mail provided was right or wrong. - # Does not affect registerable. - # config.paranoid = true - - # By default Devise will store the user in session. You can skip storage for - # particular strategies by setting this option. - # Notice that if you are skipping storage for all authentication paths, you - # may want to disable generating routes to Devise's sessions controller by - # passing skip: :sessions to `devise_for` in your config/routes.rb - config.skip_session_storage = [:http_auth] - - # By default, Devise cleans up the CSRF token on authentication to - # avoid CSRF token fixation attacks. This means that, when using AJAX - # requests for sign in and sign up, you need to get a new CSRF token - # from the server. You can disable this option at your own risk. - # config.clean_up_csrf_token_on_authentication = true - - # When false, Devise will not attempt to reload routes on eager load. - # This can reduce the time taken to boot the app but if your application - # requires the Devise mappings to be loaded during boot time the application - # won't boot properly. - # config.reload_routes = true - - # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 12. If - # using other algorithms, it sets how many times you want the password to be hashed. - # The number of stretches used for generating the hashed password are stored - # with the hashed password. This allows you to change the stretches without - # invalidating existing passwords. - # - # Limiting the stretches to just one in testing will increase the performance of - # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use - # a value less than 10 in other environments. Note that, for bcrypt (the default - # algorithm), the cost increases exponentially with the number of stretches (e.g. - # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). - config.stretches = Rails.env.test? ? 1 : 12 - - # Set up a pepper to generate the hashed password. - # config.pepper = 'b278b1d480365dd815e58307e9c2cc160350cc20c62ca4a280be2a73b2a90f645a4f461a3278a45484073e0e3830cbbd1e133d7bbaf23e1dd9d580318b6c1876' - - # Send a notification to the original email when the user's email is changed. - # config.send_email_changed_notification = false - - # Send a notification email when the user's password is changed. - # config.send_password_change_notification = false - - # ==> Configuration for :confirmable - # A period that the user is allowed to access the website even without - # confirming their account. For instance, if set to 2.days, the user will be - # able to access the website for two days without confirming their account, - # access will be blocked just in the third day. - # You can also set it to nil, which will allow the user to access the website - # without confirming their account. - # Default is 0.days, meaning the user cannot access the website without - # confirming their account. - # config.allow_unconfirmed_access_for = 2.days - - # A period that the user is allowed to confirm their account before their - # token becomes invalid. For example, if set to 3.days, the user can confirm - # their account within 3 days after the mail was sent, but on the fourth day - # their account can't be confirmed with the token any more. - # Default is nil, meaning there is no restriction on how long a user can take - # before confirming their account. - # config.confirm_within = 3.days - - # If true, requires any email changes to be confirmed (exactly the same way as - # initial account confirmation) to be applied. Requires additional unconfirmed_email - # db field (see migrations). Until confirmed, new email is stored in - # unconfirmed_email column, and copied to email column on successful confirmation. - config.reconfirmable = true - - # Defines which key will be used when confirming an account - # config.confirmation_keys = [:email] - - # ==> Configuration for :rememberable - # The time the user will be remembered without asking for credentials again. - # config.remember_for = 2.weeks - - # Invalidates all the remember me tokens when the user signs out. - config.expire_all_remember_me_on_sign_out = true - - # If true, extends the user's remember period when remembered via cookie. - # config.extend_remember_period = false - - # Options to be passed to the created cookie. For instance, you can set - # secure: true in order to force SSL only cookies. - # config.rememberable_options = {} - - # ==> Configuration for :validatable - # Range for password length. - config.password_length = 6..128 - - # Email regex used to validate email formats. It simply asserts that - # one (and only one) @ exists in the given string. This is mainly - # to give user feedback and not to assert the e-mail validity. - config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ - - # ==> Configuration for :timeoutable - # The time you want to timeout the user session without activity. After this - # time the user will be asked for credentials again. Default is 30 minutes. - # config.timeout_in = 30.minutes - - # ==> Configuration for :lockable - # Defines which strategy will be used to lock an account. - # :failed_attempts = Locks an account after a number of failed attempts to sign in. - # :none = No lock strategy. You should handle locking by yourself. - # config.lock_strategy = :failed_attempts - - # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [:email] - - # Defines which strategy will be used to unlock an account. - # :email = Sends an unlock link to the user email - # :time = Re-enables login after a certain amount of time (see :unlock_in below) - # :both = Enables both strategies - # :none = No unlock strategy. You should handle unlocking by yourself. - # config.unlock_strategy = :both - - # Number of authentication tries before locking an account if lock_strategy - # is failed attempts. - # config.maximum_attempts = 20 - - # Time interval to unlock the account if :time is enabled as unlock_strategy. - # config.unlock_in = 1.hour - - # Warn on the last attempt before the account is locked. - # config.last_attempt_warning = true - - # ==> Configuration for :recoverable - # - # Defines which key will be used when recovering the password for an account - # config.reset_password_keys = [:email] - - # Time interval you can reset your password with a reset password key. - # Don't put a too small interval or your users won't have the time to - # change their passwords. - config.reset_password_within = 6.hours - - # When set to false, does not sign a user in automatically after their password is - # reset. Defaults to true, so a user is signed in automatically after a reset. - # config.sign_in_after_reset_password = true - - # ==> Configuration for :encryptable - # Allow you to use another hashing or encryption algorithm besides bcrypt (default). - # You can use :sha1, :sha512 or algorithms from others authentication tools as - # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 - # for default behavior) and :restful_authentication_sha1 (then you should set - # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). - # - # Require the `devise-encryptable` gem when using anything other than bcrypt - # config.encryptor = :sha512 - - # ==> Scopes configuration - # Turn scoped views on. Before rendering "sessions/new", it will first check for - # "users/sessions/new". It's turned off by default because it's slower if you - # are using only default views. - # config.scoped_views = false - - # Configure the default scope given to Warden. By default it's the first - # devise role declared in your routes (usually :user). - # config.default_scope = :user - - # Set this configuration to false if you want /users/sign_out to sign out - # only the current scope. By default, Devise signs out all scopes. - # config.sign_out_all_scopes = true - - # ==> Navigation configuration - # Lists the formats that should be treated as navigational. Formats like - # :html, should redirect to the sign in page when the user does not have - # access, but formats like :xml or :json, should return 401. - # - # If you have any extra navigational formats, like :iphone or :mobile, you - # should add them to the navigational formats lists. - # - # The "*/*" below is required to match Internet Explorer requests. - # config.navigational_formats = ['*/*', :html] - - # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :delete - - # ==> OmniAuth - # Add a new OmniAuth provider. Check the wiki for more information on setting - # up on your models and hooks. - # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' - - # ==> Warden configuration - # If you want to use other strategies, that are not supported by Devise, or - # change the failure app, you can configure them inside the config.warden block. - # - # config.warden do |manager| - # manager.intercept_401 = false - # manager.default_strategies(scope: :user).unshift :some_external_strategy - # end - - # ==> Mountable engine configurations - # When using Devise inside an engine, let's call it `MyEngine`, and this engine - # is mountable, there are some extra configurations to be taken into account. - # The following options are available, assuming the engine is mounted as: - # - # mount MyEngine, at: '/my_engine' - # - # The router that invoked `devise_for`, in the example above, would be: - # config.router_name = :my_engine - # - # When using OmniAuth, Devise cannot automatically set OmniAuth path, - # so you need to do it manually. For the users scope, it would be: - # config.omniauth_path_prefix = '/my_engine/users/auth' - - # ==> Turbolinks configuration - # If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly: - # - # ActiveSupport.on_load(:devise_failure_app) do - # include Turbolinks::Controller - # end - - # ==> Configuration for :registerable - - # When set to false, does not sign a user in automatically after their password is - # changed. Defaults to true, so a user is signed in automatically after changing a password. - # config.sign_in_after_change_password = true -end diff --git a/.framework/rails/backend/config/initializers/filter_parameter_logging.rb b/.framework/rails/backend/config/initializers/filter_parameter_logging.rb deleted file mode 100644 index 4a994e1..0000000 --- a/.framework/rails/backend/config/initializers/filter_parameter_logging.rb +++ /dev/null @@ -1,4 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] diff --git a/.framework/rails/backend/config/initializers/inflections.rb b/.framework/rails/backend/config/initializers/inflections.rb deleted file mode 100644 index ac033bf..0000000 --- a/.framework/rails/backend/config/initializers/inflections.rb +++ /dev/null @@ -1,16 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format. Inflections -# are locale specific, and you may define rules for as many different -# locales as you wish. All of these examples are active by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end - -# These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' -# end diff --git a/.framework/rails/backend/config/initializers/json_param_key_transform.rb b/.framework/rails/backend/config/initializers/json_param_key_transform.rb deleted file mode 100644 index 7f88929..0000000 --- a/.framework/rails/backend/config/initializers/json_param_key_transform.rb +++ /dev/null @@ -1,17 +0,0 @@ -# File: config/initializers/json_param_key_transform.rb -# Transform JSON request param keys from JSON-conventional camelCase to -# Rails-conventional snake_case: -ActionDispatch::Request.parameter_parsers[:json] = lambda { |raw_post| - # Modified from action_dispatch/http/parameters.rb - data = ActiveSupport::JSON.decode(raw_post) - - # Transform camelCase param keys to snake_case - if data.is_a?(Array) - data.map { |item| item.deep_transform_keys!(&:underscore) } - else - data.deep_transform_keys!(&:underscore) - end - - # Return data - data.is_a?(Hash) ? data : { '_json': data } -} diff --git a/.framework/rails/backend/config/initializers/mime_types.rb b/.framework/rails/backend/config/initializers/mime_types.rb deleted file mode 100644 index dc18996..0000000 --- a/.framework/rails/backend/config/initializers/mime_types.rb +++ /dev/null @@ -1,4 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new mime types for use in respond_to blocks: -# Mime::Type.register "text/richtext", :rtf diff --git a/.framework/rails/backend/config/initializers/wrap_parameters.rb b/.framework/rails/backend/config/initializers/wrap_parameters.rb deleted file mode 100644 index bbfc396..0000000 --- a/.framework/rails/backend/config/initializers/wrap_parameters.rb +++ /dev/null @@ -1,14 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# This file contains settings for ActionController::ParamsWrapper which -# is enabled by default. - -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. -ActiveSupport.on_load(:action_controller) do - wrap_parameters format: [:json] -end - -# To enable root element in JSON for ActiveRecord objects. -# ActiveSupport.on_load(:active_record) do -# self.include_root_in_json = true -# end diff --git a/.framework/rails/backend/config/locales/devise.en.yml b/.framework/rails/backend/config/locales/devise.en.yml deleted file mode 100644 index 260e1c4..0000000 --- a/.framework/rails/backend/config/locales/devise.en.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Additional translations at https://github.com/heartcombo/devise/wiki/I18n - -en: - devise: - confirmations: - confirmed: "Your email address has been successfully confirmed." - send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." - send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." - failure: - already_authenticated: "You are already signed in." - inactive: "Your account is not activated yet." - invalid: "Invalid %{authentication_keys} or password." - locked: "Your account is locked." - last_attempt: "You have one more attempt before your account is locked." - not_found_in_database: "Invalid %{authentication_keys} or password." - timeout: "Your session expired. Please sign in again to continue." - unauthenticated: "You need to sign in or sign up before continuing." - unconfirmed: "You have to confirm your email address before continuing." - mailer: - confirmation_instructions: - subject: "Confirmation instructions" - reset_password_instructions: - subject: "Reset password instructions" - unlock_instructions: - subject: "Unlock instructions" - email_changed: - subject: "Email Changed" - password_change: - subject: "Password Changed" - omniauth_callbacks: - failure: "Could not authenticate you from %{kind} because \"%{reason}\"." - success: "Successfully authenticated from %{kind} account." - passwords: - no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." - send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." - send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." - updated: "Your password has been changed successfully. You are now signed in." - updated_not_active: "Your password has been changed successfully." - registrations: - destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." - signed_up: "Welcome! You have signed up successfully." - signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." - signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." - signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." - update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address." - updated: "Your account has been updated successfully." - updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again." - sessions: - signed_in: "Signed in successfully." - signed_out: "Signed out successfully." - already_signed_out: "Signed out successfully." - unlocks: - send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." - send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." - unlocked: "Your account has been unlocked successfully. Please sign in to continue." - errors: - messages: - already_confirmed: "was already confirmed, please try signing in" - confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" - expired: "has expired, please request a new one" - not_found: "not found" - not_locked: "was not locked" - not_saved: - one: "1 error prohibited this %{resource} from being saved:" - other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/.framework/rails/backend/config/locales/en.yml b/.framework/rails/backend/config/locales/en.yml deleted file mode 100644 index decc5a8..0000000 --- a/.framework/rails/backend/config/locales/en.yml +++ /dev/null @@ -1,33 +0,0 @@ -# Files in the config/locales directory are used for internationalization -# and are automatically loaded by Rails. If you want to use locales other -# than English, add the necessary files in this directory. -# -# To use the locales, use `I18n.t`: -# -# I18n.t 'hello' -# -# In views, this is aliased to just `t`: -# -# <%= t('hello') %> -# -# To use a different locale, set it with `I18n.locale`: -# -# I18n.locale = :es -# -# This would use the information in config/locales/es.yml. -# -# The following keys must be escaped otherwise they will not be retrieved by -# the default I18n backend: -# -# true, false, on, off, yes, no -# -# Instead, surround them with single quotes. -# -# en: -# 'true': 'foo' -# -# To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. - -en: - hello: "Hello world" diff --git a/.framework/rails/backend/config/locales/responders.en.yml b/.framework/rails/backend/config/locales/responders.en.yml deleted file mode 100644 index c3e147a..0000000 --- a/.framework/rails/backend/config/locales/responders.en.yml +++ /dev/null @@ -1,12 +0,0 @@ -en: - flash: - actions: - create: - notice: '%{resource_name} was successfully created.' - # alert: '%{resource_name} could not be created.' - update: - notice: '%{resource_name} was successfully updated.' - # alert: '%{resource_name} could not be updated.' - destroy: - notice: '%{resource_name} was successfully destroyed.' - alert: '%{resource_name} could not be destroyed.' diff --git a/.framework/rails/backend/config/puma.rb b/.framework/rails/backend/config/puma.rb deleted file mode 100644 index db6198c..0000000 --- a/.framework/rails/backend/config/puma.rb +++ /dev/null @@ -1,34 +0,0 @@ -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. -# -threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -threads threads_count, threads_count - -# Specifies the `port` that Puma will listen on to receive requests; default is 3000. -# -port ENV.fetch("PORT") { 3000 } - -# Specifies the `environment` that Puma will run in. -# -environment ENV.fetch("RAILS_ENV") { "development" } - -# Specifies the number of `workers` to boot in clustered mode. -# Workers are forked webserver processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). -# -workers ENV.fetch("WEB_CONCURRENCY") { 3 } - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. -# -preload_app! - -# Allow puma to be restarted by `rails restart` command. -plugin :tmp_restart diff --git a/.framework/rails/backend/config/routes.rb b/.framework/rails/backend/config/routes.rb deleted file mode 100644 index b5ff26a..0000000 --- a/.framework/rails/backend/config/routes.rb +++ /dev/null @@ -1,27 +0,0 @@ - -Rails.application.routes.draw do - root to: "application#root" - - get '/health', to: 'application#health' - - scope :api, defaults: { format: :json } do - devise_for :users, controllers: { sessions: :sessions, registrations: :registrations }, - path_names: { sign_in: :login } - - resource :user, only: %i[show update] - - resources :profiles, param: :username, only: [:show] do - resource :follow, only: %i[create destroy] - end - - resources :items, param: :slug, except: %i[edit new] do - resource :favorite, only: %i[create destroy] - resources :comments, only: %i[create index destroy] - get :feed, on: :collection - end - - resources :tags, only: [:index] - - resources :ping, only: [:index] - end -end diff --git a/.framework/rails/backend/config/secrets.yml b/.framework/rails/backend/config/secrets.yml deleted file mode 100644 index 5482bab..0000000 --- a/.framework/rails/backend/config/secrets.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key is used for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! - -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -# You can use `rails secret` to generate a secure secret key. - -# Make sure the secrets in this file are kept private -# if you're sharing your code publicly. - -# Shared secrets are available across all environments. - -shared: - -# Environmental secrets are only available for that specific environment. - -production: - secret_key_base: ceda0b32a04e63a9b997ec109c980c090bfa85cbdf26fc44288633dc9847b03ad8c460de5bcdb81e7cc0b0f158bb9b11a40105277a44e8d47e18e6639dd8d793 - -development: - secret_key_base: b4ec4bebe065b6d81ff57acc4c81464d6ce8e8488a67391e0d51f2707ebc4ea474d86fa6c52d22adefd141f7236d6f99da046f4945c4773e6ff5f100eb4f29ed - -test: - secret_key_base: 25c0c6b3cfc81e9357d13657f5545d3401da7af97a2be88c37c0d5afff8913f49fa2ba5dd75c21fedc8a974e27a8bd486f318510944899eb535175a5359a7277 diff --git a/.framework/rails/backend/config/secrets.yml.enc b/.framework/rails/backend/config/secrets.yml.enc deleted file mode 100644 index 534adbb..0000000 --- a/.framework/rails/backend/config/secrets.yml.enc +++ /dev/null @@ -1 +0,0 @@ -siBQfbvp2QIrFrw2Nb+S2ZJOKgQrXbV7tHsJWYafnxnruINEIo57G1+KVXIqfTFbvL95wh9R5dKoJj/7iJXk73KUv6VGg2AvmaWU9wEr9/nQsy2ojNAtg6F0T6ImsrzZchRDmycSPQkbQRBeqjDhuHqumSy8sqQOWeeIGM/4A99OxmCQIa2cAoQ09X38Og==--f7rABLaEoAVbrEWg--O15KZL5f10Z882jBsk4udA== \ No newline at end of file diff --git a/.framework/rails/backend/config/spring.rb b/.framework/rails/backend/config/spring.rb deleted file mode 100644 index 9fa7863..0000000 --- a/.framework/rails/backend/config/spring.rb +++ /dev/null @@ -1,6 +0,0 @@ -%w[ - .ruby-version - .rbenv-vars - tmp/restart.txt - tmp/caching-dev.txt -].each { |path| Spring.watch(path) } diff --git a/.framework/rails/backend/config/storage.yml b/.framework/rails/backend/config/storage.yml deleted file mode 100644 index d32f76e..0000000 --- a/.framework/rails/backend/config/storage.yml +++ /dev/null @@ -1,34 +0,0 @@ -test: - service: Disk - root: <%= Rails.root.join("tmp/storage") %> - -local: - service: Disk - root: <%= Rails.root.join("storage") %> - -# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) -# amazon: -# service: S3 -# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> -# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> -# region: us-east-1 -# bucket: your_own_bucket - -# Remember not to checkin your GCS keyfile to a repository -# google: -# service: GCS -# project: your_project -# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> -# bucket: your_own_bucket - -# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) -# microsoft: -# service: AzureStorage -# storage_account_name: your_account_name -# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> -# container: your_container_name - -# mirror: -# service: Mirror -# primary: local -# mirrors: [ amazon, google, microsoft ] diff --git a/.framework/rails/backend/db/migrate/20210412045707_devise_create_users.rb b/.framework/rails/backend/db/migrate/20210412045707_devise_create_users.rb deleted file mode 100644 index 78f4547..0000000 --- a/.framework/rails/backend/db/migrate/20210412045707_devise_create_users.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -class DeviseCreateUsers < ActiveRecord::Migration[4.2] - def change - create_table :users do |t| - ## Database authenticatable - t.string :email, null: false, default: '' - t.string :encrypted_password, null: false, default: '' - - ## Recoverable - t.string :reset_password_token - t.datetime :reset_password_sent_at - - ## Rememberable - t.datetime :remember_created_at - - ## Trackable - t.integer :sign_in_count, default: 0, null: false - t.datetime :current_sign_in_at - t.datetime :last_sign_in_at - t.string :current_sign_in_ip - t.string :last_sign_in_ip - - ## Confirmable - # t.string :confirmation_token - # t.datetime :confirmed_at - # t.datetime :confirmation_sent_at - # t.string :unconfirmed_email # Only if using reconfirmable - - ## Lockable - # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts - # t.string :unlock_token # Only if unlock strategy is :email or :both - # t.datetime :locked_at - - t.timestamps null: false - end - - add_index :users, :email, unique: true - add_index :users, :reset_password_token, unique: true - # add_index :users, :confirmation_token, unique: true - # add_index :users, :unlock_token, unique: true - end -end diff --git a/.framework/rails/backend/db/migrate/20210412045739_add_profile_fields_to_users.rb b/.framework/rails/backend/db/migrate/20210412045739_add_profile_fields_to_users.rb deleted file mode 100644 index 1230e71..0000000 --- a/.framework/rails/backend/db/migrate/20210412045739_add_profile_fields_to_users.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -class AddProfileFieldsToUsers < ActiveRecord::Migration[5.0] - def change - add_column :users, :username, :string - add_index :users, :username, unique: true - add_column :users, :image, :string - add_column :users, :bio, :text - end -end diff --git a/.framework/rails/backend/db/migrate/20210412052128_create_items.rb b/.framework/rails/backend/db/migrate/20210412052128_create_items.rb deleted file mode 100644 index 7b6cd3d..0000000 --- a/.framework/rails/backend/db/migrate/20210412052128_create_items.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -class CreateItems < ActiveRecord::Migration[5.0] - def change - create_table :items do |t| - t.string :title - t.string :slug - t.string :description - t.string :image - t.integer :favorites_count - t.references :user, index: true, foreign_key: true - - t.timestamps null: false - end - add_index :items, :slug, unique: true - end -end diff --git a/.framework/rails/backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/.framework/rails/backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb deleted file mode 100644 index 14d8c35..0000000 --- a/.framework/rails/backend/db/migrate/20210412054809_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -# This migration comes from acts_as_taggable_on_engine (originally 1) -class ActsAsTaggableOnMigration < ActiveRecord::Migration[5.0] - def self.up - create_table :tags do |t| - t.string :name - end - - create_table :taggings do |t| - t.references :tag - - # You should make sure that the column created is - # long enough to store the required class names. - t.references :taggable, polymorphic: true - t.references :tagger, polymorphic: true - - # Limit is created to prevent MySQL error on index - # length for MyISAM table type: http://bit.ly/vgW2Ql - t.string :context, limit: 128 - - t.datetime :created_at - end - - add_index :taggings, :tag_id unless index_exists?(:taggings, :tag_id) - add_index :taggings, %i[taggable_id taggable_type context] - end - - def self.down - drop_table :taggings - drop_table :tags - end -end diff --git a/.framework/rails/backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/.framework/rails/backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb deleted file mode 100644 index c0aa721..0000000 --- a/.framework/rails/backend/db/migrate/20210412054810_add_missing_unique_indices.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -# This migration comes from acts_as_taggable_on_engine (originally 2) -class AddMissingUniqueIndices < ActiveRecord::Migration[5.0] - def self.up - add_index :tags, :name, unique: true - - remove_index :taggings, :tag_id - remove_index :taggings, %i[taggable_id taggable_type context] - add_index :taggings, - %i[tag_id taggable_id taggable_type context tagger_id tagger_type], - unique: true, name: 'taggings_idx' - end - - def self.down - remove_index :tags, :name - - remove_index :taggings, name: 'taggings_idx' - add_index :taggings, :tag_id - add_index :taggings, %i[taggable_id taggable_type context] - end -end diff --git a/.framework/rails/backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/.framework/rails/backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb deleted file mode 100644 index 871f96f..0000000 --- a/.framework/rails/backend/db/migrate/20210412054811_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -# This migration comes from acts_as_taggable_on_engine (originally 3) -class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[5.0] - def self.up - add_column :tags, :taggings_count, :integer, default: 0 - - ActsAsTaggableOn::Tag.reset_column_information - ActsAsTaggableOn::Tag.find_each do |tag| - ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) - end - end - - def self.down - remove_column :tags, :taggings_count - end -end diff --git a/.framework/rails/backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/.framework/rails/backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb deleted file mode 100644 index 42fe2b7..0000000 --- a/.framework/rails/backend/db/migrate/20210412054812_add_missing_taggable_index.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -# This migration comes from acts_as_taggable_on_engine (originally 4) -class AddMissingTaggableIndex < ActiveRecord::Migration[5.0] - def self.up - add_index :taggings, %i[taggable_id taggable_type context] - end - - def self.down - remove_index :taggings, %i[taggable_id taggable_type context] - end -end diff --git a/.framework/rails/backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/.framework/rails/backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb deleted file mode 100644 index 29a11e3..0000000 --- a/.framework/rails/backend/db/migrate/20210412054813_change_collation_for_tag_names.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -# This migration comes from acts_as_taggable_on_engine (originally 5) -# This migration is added to circumvent issue #623 and have special characters -# work properly -class ChangeCollationForTagNames < ActiveRecord::Migration[5.0] - def up - if ActsAsTaggableOn::Utils.using_mysql? - execute('ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;') - end - end -end diff --git a/.framework/rails/backend/db/migrate/20210412055201_create_favorites.rb b/.framework/rails/backend/db/migrate/20210412055201_create_favorites.rb deleted file mode 100644 index f9ef870..0000000 --- a/.framework/rails/backend/db/migrate/20210412055201_create_favorites.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -class CreateFavorites < ActiveRecord::Migration[5.0] - def change - create_table :favorites do |t| - t.references :user, index: true, foreign_key: true - t.references :item, index: true, foreign_key: true - - t.timestamps null: false - end - end -end diff --git a/.framework/rails/backend/db/migrate/20210412061113_create_comments.rb b/.framework/rails/backend/db/migrate/20210412061113_create_comments.rb deleted file mode 100644 index 12ccb33..0000000 --- a/.framework/rails/backend/db/migrate/20210412061113_create_comments.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -class CreateComments < ActiveRecord::Migration[5.0] - def change - create_table :comments do |t| - t.text :body - t.references :user, index: true, foreign_key: true - t.references :item, index: true, foreign_key: true - - t.timestamps null: false - end - end -end diff --git a/.framework/rails/backend/db/migrate/20210412061614_acts_as_follower_migration.rb b/.framework/rails/backend/db/migrate/20210412061614_acts_as_follower_migration.rb deleted file mode 100644 index 3fd715a..0000000 --- a/.framework/rails/backend/db/migrate/20210412061614_acts_as_follower_migration.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -class ActsAsFollowerMigration < ActiveRecord::Migration[5.0] - def self.up - create_table :follows, force: true do |t| - t.references :followable, polymorphic: true, null: false - t.references :follower, polymorphic: true, null: false - t.boolean :blocked, default: false, null: false - t.timestamps - end - - add_index :follows, %w[follower_id follower_type], name: 'fk_follows' - add_index :follows, %w[followable_id followable_type], name: 'fk_followables' - end - - def self.down - drop_table :follows - end -end diff --git a/.framework/rails/backend/db/schema.rb b/.framework/rails/backend/db/schema.rb deleted file mode 100644 index 44d2262..0000000 --- a/.framework/rails/backend/db/schema.rb +++ /dev/null @@ -1,110 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# This file is the source Rails uses to define your schema when running `bin/rails -# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to -# be faster and is potentially less error prone than running all of your -# migrations from scratch. Old migrations may fail to apply correctly if those -# migrations use external dependencies or application code. -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 2021_04_12_061614) do - - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" - - create_table "comments", id: :serial, force: :cascade do |t| - t.text "body" - t.integer "user_id" - t.integer "item_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["item_id"], name: "index_comments_on_item_id" - t.index ["user_id"], name: "index_comments_on_user_id" - end - - create_table "favorites", id: :serial, force: :cascade do |t| - t.integer "user_id" - t.integer "item_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["item_id"], name: "index_favorites_on_item_id" - t.index ["user_id"], name: "index_favorites_on_user_id" - end - - create_table "follows", id: :serial, force: :cascade do |t| - t.string "followable_type", null: false - t.integer "followable_id", null: false - t.string "follower_type", null: false - t.integer "follower_id", null: false - t.boolean "blocked", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["followable_id", "followable_type"], name: "fk_followables" - t.index ["followable_type", "followable_id"], name: "index_follows_on_followable" - t.index ["follower_id", "follower_type"], name: "fk_follows" - t.index ["follower_type", "follower_id"], name: "index_follows_on_follower" - end - - create_table "items", id: :serial, force: :cascade do |t| - t.string "title" - t.string "slug" - t.string "description" - t.string "image" - t.integer "favorites_count" - t.integer "user_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["slug"], name: "index_items_on_slug", unique: true - t.index ["user_id"], name: "index_items_on_user_id" - end - - create_table "taggings", id: :serial, force: :cascade do |t| - t.integer "tag_id" - t.string "taggable_type" - t.integer "taggable_id" - t.string "tagger_type" - t.integer "tagger_id" - t.string "context", limit: 128 - t.datetime "created_at" - t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true - t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context" - t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable" - t.index ["tagger_type", "tagger_id"], name: "index_taggings_on_tagger" - end - - create_table "tags", id: :serial, force: :cascade do |t| - t.string "name" - t.integer "taggings_count", default: 0 - t.index ["name"], name: "index_tags_on_name", unique: true - end - - create_table "users", id: :serial, force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at" - t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "username" - t.string "image" - t.text "bio" - t.index ["email"], name: "index_users_on_email", unique: true - t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true - t.index ["username"], name: "index_users_on_username", unique: true - end - - add_foreign_key "comments", "items" - add_foreign_key "comments", "users" - add_foreign_key "favorites", "items" - add_foreign_key "favorites", "users" - add_foreign_key "items", "users" -end diff --git a/.framework/rails/backend/db/seeds.rb b/.framework/rails/backend/db/seeds.rb deleted file mode 100644 index 1beea2a..0000000 --- a/.framework/rails/backend/db/seeds.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). -# -# Examples: -# -# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) -# Character.create(name: 'Luke', movie: movies.first) diff --git a/.framework/rails/backend/lib/assets/.keep b/.framework/rails/backend/lib/assets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/lib/event.rb b/.framework/rails/backend/lib/event.rb deleted file mode 100644 index d548df7..0000000 --- a/.framework/rails/backend/lib/event.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Event - def sendEvent(eventName, metadata) - wilcoId = ENV['WILCO_ID'] || File.read(Rails.root.join("../.wilco")) - baseUrl = ENV['ENGINE_BASE_URL'] || "https://engine.wilco.gg" - conn = Faraday.new( - url: baseUrl + "/users/#{wilcoId}/", - headers: {'Content-Type' => 'application/json'} - ) - begin - response = conn.post('event') do |req| - req.headers['Content-Type'] = 'application/json' - req.body = { event: eventName, metadata: metadata}.to_json - end - rescue Exception => e - puts 'failed to send event #{wilcoId} to Wilco engine' - end - response - end -end diff --git a/.framework/rails/backend/lib/tasks/.keep b/.framework/rails/backend/lib/tasks/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/log/.keep b/.framework/rails/backend/log/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/public/404.html b/.framework/rails/backend/public/404.html deleted file mode 100644 index b612547..0000000 --- a/.framework/rails/backend/public/404.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - The page you were looking for doesn't exist (404) - - - - - - -
-
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/.framework/rails/backend/public/422.html b/.framework/rails/backend/public/422.html deleted file mode 100644 index a21f82b..0000000 --- a/.framework/rails/backend/public/422.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - The change you wanted was rejected (422) - - - - - - -
-
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/.framework/rails/backend/public/500.html b/.framework/rails/backend/public/500.html deleted file mode 100644 index 061abc5..0000000 --- a/.framework/rails/backend/public/500.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - We're sorry, but something went wrong (500) - - - - - - -
-
-

We're sorry, but something went wrong.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/.framework/rails/backend/public/favicon.ico b/.framework/rails/backend/public/favicon.ico deleted file mode 100644 index e69de29..0000000 diff --git a/.framework/rails/backend/public/robots.txt b/.framework/rails/backend/public/robots.txt deleted file mode 100644 index 37b576a..0000000 --- a/.framework/rails/backend/public/robots.txt +++ /dev/null @@ -1 +0,0 @@ -# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/.framework/rails/backend/seeds.sh b/.framework/rails/backend/seeds.sh deleted file mode 100755 index 8c1a5b6..0000000 --- a/.framework/rails/backend/seeds.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -bin/rails db:seed diff --git a/.framework/rails/backend/start.sh b/.framework/rails/backend/start.sh deleted file mode 100755 index bc5a109..0000000 --- a/.framework/rails/backend/start.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -bundle exec rails s diff --git a/.framework/rails/backend/start_rails.sh b/.framework/rails/backend/start_rails.sh deleted file mode 100755 index eec24c7..0000000 --- a/.framework/rails/backend/start_rails.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -rm -f /tmp/server.pid -bin/rails db:migrate -bin/rails s -b 0.0.0.0 --pid /tmp/server.pid 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-deployment.yaml b/.framework/rails/charts/templates/anythink-backend-deployment.yaml deleted file mode 100644 index a71f3a7..0000000 --- a/.framework/rails/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 - - "rm -f /tmp/server.pid && exec rails s -b 0.0.0.0 --pid /tmp/server.pid" - env: - - name: DATABASE_URL - value: "{{ .Values.database.connectionProtocol}}{{ .Values.database.env.userName}}:@{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}" - - name: RAILS_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 }} - initContainers: - - command: - - sh - - -c - - "rails db:migrate && ./seeds.sh" - env: - - name: DATABASE_URL - value: "{{ .Values.database.connectionProtocol}}{{ .Values.database.env.userName}}:@{{ .Values.database.serviceName }}:{{ .Values.database.servicePort }}" - - name: RAILS_ENV - value: development - - name: PORT - value: "{{ .Values.backend.containerPort }}" - image: "{{ include "anythink-tenant.backendRepository" .}}:{{ .Values.backend.image.tag }}" - imagePullPolicy: {{ .Values.backend.image.pullPolicy }} - name: db-migrations - restartPolicy: Always 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-deployment.yaml b/.framework/rails/charts/templates/database-deployment.yaml deleted file mode 100644 index 667a23a..0000000 --- a/.framework/rails/charts/templates/database-deployment.yaml +++ /dev/null @@ -1,42 +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 }} - 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/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/rails/charts/values.yaml b/.framework/rails/charts/values.yaml deleted file mode 100644 index 026452c..0000000 --- a/.framework/rails/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: postgres:// - serviceName: postgres-rails - containerPort: 5433 - servicePort: 5432 - replicaCount: 1 - env: - userName: user - password: password - 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/rails/docker-compose.yml b/.framework/rails/docker-compose.yml deleted file mode 100644 index 5447d2b..0000000 --- a/.framework/rails/docker-compose.yml +++ /dev/null @@ -1,61 +0,0 @@ -version: "3.8" -services: - anythink-backend-rails: - build: ./backend - container_name: anythink-backend-rails - command: sh -c "cd backend && bundle install && /wait-for-it.sh postgres-rails:5432 -q -t 60 && ./start_rails.sh" - - working_dir: /usr/src - volumes: - - ./:/usr/src/ - ports: - - "3000:3000" - environment: - - RAILS_ENV=development - - PORT=3000 - - DATABASE_URL=postgres://user:@postgres-rails:5432 - - GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN=${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN} - depends_on: - - "postgres-rails" - - anythink-frontend-react: - build: ./frontend - container_name: anythink-frontend-react - command: sh -c "cd frontend && yarn install && /wait-for-it.sh anythink-backend-rails:3000 -t 120 --strict -- curl --head -X GET --retry 30 --retry-connrefused --retry-delay 1 anythink-backend-rails: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-rails" - - postgres-rails: - container_name: postgres-rails - restart: on-failure - image: postgres - logging: - driver: none - environment: - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_USER: user - POSTGRES_PASSWORD: password - volumes: - - ~/posgres/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/react/frontend/.gitignore b/.framework/react/frontend/.gitignore deleted file mode 100644 index edfc119..0000000 --- a/.framework/react/frontend/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# dependencies -node_modules - -# testing -coverage - -# production -build - -# misc -.DS_Store -.env -npm-debug.log -.idea \ No newline at end of file diff --git a/.framework/react/frontend/Dockerfile b/.framework/react/frontend/Dockerfile deleted file mode 100644 index c8ba554..0000000 --- a/.framework/react/frontend/Dockerfile +++ /dev/null @@ -1 +0,0 @@ -FROM public.ecr.aws/v0a2l7y2/wilco/anythink-frontend-react:latest diff --git a/.framework/react/frontend/Dockerfile.aws b/.framework/react/frontend/Dockerfile.aws deleted file mode 100644 index 9485ac1..0000000 --- a/.framework/react/frontend/Dockerfile.aws +++ /dev/null @@ -1,9 +0,0 @@ -FROM node:16 -WORKDIR /usr/src - -COPY frontend ./frontend -COPY .wilco ./.wilco - -# Pre-install npm packages -WORKDIR /usr/src/frontend -RUN yarn install diff --git a/.framework/react/frontend/jest.config.js b/.framework/react/frontend/jest.config.js deleted file mode 100644 index 582fe82..0000000 --- a/.framework/react/frontend/jest.config.js +++ /dev/null @@ -1,8 +0,0 @@ -const config = { - verbose: true, - jest: { - setupFilesAfterEnv: ["src/setupTests.js"], - }, -}; - -module.exports = config; diff --git a/.framework/react/frontend/package.json b/.framework/react/frontend/package.json deleted file mode 100644 index 45a643d..0000000 --- a/.framework/react/frontend/package.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "anythink-market-front", - "version": "0.1.0", - "engines": { - "node": "^16" - }, - "private": true, - "devDependencies": { - "@wojtekmaj/enzyme-adapter-react-17": "^0.6.7", - "core-js": "^3.25.1", - "enzyme": "^3.11.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-react": "^7.26.1", - "prettier": "2.4.1", - "react-test-renderer": "^17.0.2", - "redux-mock-store": "^1.5.4" - }, - "dependencies": { - "@babel/core": "^7.18.13", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-syntax-flow": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.10", - "bootstrap": "^4.6.0", - "bootstrap-icons": "^1.7.1", - "history": "^4.6.3", - "jquery": "^3.6.1", - "marked": "^0.3.6", - "postcss": "^8.4.16", - "prop-types": "^15.5.10", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-redux": "^5.0.7", - "react-router-dom": "^6.9.0", - "react-scripts": "^5.0.1", - "redux": "^3.6.0", - "redux-devtools-extension": "^2.13.2", - "sass": "^1.45.0", - "superagent": "^3.8.2", - "superagent-promise": "^1.1.0", - "typescript": "^4.8.2" - }, - "scripts": { - "start": "REACT_APP_WILCO_ID=${WILCO_ID:-\"$(cat ../.wilco)\"} react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject", - "format": "yarn prettier --write .", - "lint": "yarn eslint . && yarn prettier --check ." - }, - "eslintConfig": { - "extends": [ - "react-app", - "eslint:recommended" - ], - "rules": { - "no-var": "error" - } - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "resolutions": { - "autoprefixer": "10.4.5" - } -} diff --git a/.framework/react/frontend/public/50precentoff.png b/.framework/react/frontend/public/50precentoff.png deleted file mode 100644 index 4c835a1..0000000 Binary files a/.framework/react/frontend/public/50precentoff.png and /dev/null differ diff --git a/.framework/react/frontend/public/favicon.ico b/.framework/react/frontend/public/favicon.ico deleted file mode 100644 index 201ae78..0000000 Binary files a/.framework/react/frontend/public/favicon.ico and /dev/null differ diff --git a/.framework/react/frontend/public/index.html b/.framework/react/frontend/public/index.html deleted file mode 100644 index f0441fc..0000000 --- a/.framework/react/frontend/public/index.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - Anythink Market - - -
-
- - diff --git a/.framework/react/frontend/public/placeholder.png b/.framework/react/frontend/public/placeholder.png deleted file mode 100644 index bf1d310..0000000 Binary files a/.framework/react/frontend/public/placeholder.png and /dev/null differ diff --git a/.framework/react/frontend/public/style.css b/.framework/react/frontend/public/style.css deleted file mode 100644 index 2bb7fe2..0000000 --- a/.framework/react/frontend/public/style.css +++ /dev/null @@ -1,54 +0,0 @@ -* { - -webkit-font-smoothing: antialiased; -} -body { - font-family: "Inter", sans-serif; - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - text-rendering: optimizeLegibility; - -moz-osx-font-smoothing: grayscale; - -webkit-font-feature-settings: "kern" 1, "liga" 1; - font-feature-settings: "kern" 1, "liga" 1; - scroll-behavior: smooth; -} -.top-announcement { - background-color: #59ca00; - padding: 15px; - font-size: 18px; - color: white; -} -.logo-text { - color: #59ca00 !important; - font-weight: 600; -} -.minegeek-navbar { - background-color: #393939; -} -.sunray { - background-image: url("sunray.jpeg"); - background-size: cover; -} -.text-white { - color: white; -} -.row-eq-height { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -} -.minegear-btn { - background-color: #59ca00; - border: 0px; - border-radius: 0px; -} -.dramaticPerson { - opacity: 0; - position: fixed; - right: -500px; - bottom: 0px; - height: 590px; - width: 490px; - z-index: 1041; - background-size: cover; -} diff --git a/.framework/react/frontend/public/sunray.jpeg b/.framework/react/frontend/public/sunray.jpeg deleted file mode 100644 index f133496..0000000 Binary files a/.framework/react/frontend/public/sunray.jpeg and /dev/null differ diff --git a/.framework/react/frontend/public/verified_seller.svg b/.framework/react/frontend/public/verified_seller.svg deleted file mode 100644 index 2e1b353..0000000 --- a/.framework/react/frontend/public/verified_seller.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - diff --git a/.framework/react/frontend/readme.md b/.framework/react/frontend/readme.md deleted file mode 100644 index 2f5bc17..0000000 --- a/.framework/react/frontend/readme.md +++ /dev/null @@ -1,26 +0,0 @@ -# Anythink Frontend - -The Anythink Frontend is an SPA written with [React](https://reactjs.org/) and [Redux](https://redux.js.org/) - -## Getting started - -Make sure your server is up and running to serve requests. - -## Pages overview - -- Home page (URL: /#/ ) - - List of tags - - List of items pulled from either Feed, Global, or by Tag - - Pagination for list of items -- Sign in/Sign up pages (URL: /#/login, /#/register ) - - Use JWT (store the token in localStorage) -- Settings page (URL: /#/settings ) -- Editor page to create/edit articles (URL: /#/editor, /#/editor/slug ) -- Item page (URL: /#/item/slug ) - - Delete item button (only shown to item's author) - - Render markdown from server client side - - Comments section at bottom of page - - Delete comment button (only shown to comment's author) -- Profile page (URL: /#/@username, /#/@username/favorites ) - - Show basic user info - - List of items populated from seller's items or user favorite items diff --git a/.framework/react/frontend/src/agent.js b/.framework/react/frontend/src/agent.js deleted file mode 100644 index 972f3e3..0000000 --- a/.framework/react/frontend/src/agent.js +++ /dev/null @@ -1,98 +0,0 @@ -import superagentPromise from "superagent-promise"; -import _superagent from "superagent"; - -const superagent = superagentPromise(_superagent, global.Promise); - -const BACKEND_URL = - process.env.NODE_ENV !== "production" - ? process.env.REACT_APP_BACKEND_URL - : "https://api.anythink.market"; - -const API_ROOT = `${BACKEND_URL}/api`; - -const encode = encodeURIComponent; -const responseBody = (res) => res.body; - -let token = null; -const tokenPlugin = (req) => { - if (token) { - req.set("authorization", `Token ${token}`); - } -}; - -const requests = { - del: (url) => - superagent.del(`${API_ROOT}${url}`).use(tokenPlugin).then(responseBody), - get: (url) => - superagent.get(`${API_ROOT}${url}`).use(tokenPlugin).then(responseBody), - put: (url, body) => - superagent - .put(`${API_ROOT}${url}`, body) - .use(tokenPlugin) - .then(responseBody), - post: (url, body) => - superagent - .post(`${API_ROOT}${url}`, body) - .use(tokenPlugin) - .then(responseBody), -}; - -const Auth = { - current: () => requests.get("/user"), - login: (email, password) => - requests.post("/users/login", { user: { email, password } }), - register: (username, email, password) => - requests.post("/users", { user: { username, email, password } }), - save: (user) => requests.put("/user", { user }), -}; - -const Tags = { - getAll: () => requests.get("/tags"), -}; - -const limit = (count, p) => `limit=${count}&offset=${p ? p * count : 0}`; -const omitSlug = (item) => Object.assign({}, item, { slug: undefined }); -const Items = { - all: (page) => requests.get(`/items?${limit(1000, page)}`), - bySeller: (seller, page) => - requests.get(`/items?seller=${encode(seller)}&${limit(500, page)}`), - byTag: (tag, page) => - requests.get(`/items?tag=${encode(tag)}&${limit(1000, page)}`), - del: (slug) => requests.del(`/items/${slug}`), - favorite: (slug) => requests.post(`/items/${slug}/favorite`), - favoritedBy: (seller, page) => - requests.get(`/items?favorited=${encode(seller)}&${limit(500, page)}`), - feed: () => requests.get("/items/feed?limit=10&offset=0"), - get: (slug) => requests.get(`/items/${slug}`), - unfavorite: (slug) => requests.del(`/items/${slug}/favorite`), - update: (item) => - requests.put(`/items/${item.slug}`, { item: omitSlug(item) }), - create: (item) => requests.post("/items", { item }), -}; - -const Comments = { - create: (slug, comment) => - requests.post(`/items/${slug}/comments`, { comment }), - delete: (slug, commentId) => - requests.del(`/items/${slug}/comments/${commentId}`), - forItem: (slug) => requests.get(`/items/${slug}/comments`), -}; - -const Profile = { - follow: (username) => requests.post(`/profiles/${username}/follow`), - get: (username) => requests.get(`/profiles/${username}`), - unfollow: (username) => requests.del(`/profiles/${username}/follow`), -}; - -const agentObj = { - Items, - Auth, - Comments, - Profile, - Tags, - setToken: (_token) => { - token = _token; - }, -}; - -export default agentObj; diff --git a/.framework/react/frontend/src/components/App.js b/.framework/react/frontend/src/components/App.js deleted file mode 100644 index 8b23812..0000000 --- a/.framework/react/frontend/src/components/App.js +++ /dev/null @@ -1,81 +0,0 @@ -import agent from "../agent"; -import Header from "./Header"; -import React, { useEffect } from "react"; -import { connect } from "react-redux"; -import { APP_LOAD, REDIRECT } from "../constants/actionTypes"; -import Item from "./Item"; -import Editor from "./Editor"; -import Home from "./Home"; -import Login from "./Login"; -import Profile from "./Profile"; -import ProfileFavorites from "./ProfileFavorites"; -import Register from "./Register"; -import Settings from "./Settings"; -import { Route, Routes, useNavigate } from "react-router-dom"; - -const mapStateToProps = (state) => { - return { - appLoaded: state.common.appLoaded, - appName: state.common.appName, - currentUser: state.common.currentUser, - redirectTo: state.common.redirectTo, - }; -}; - -const mapDispatchToProps = (dispatch) => ({ - onLoad: (payload, token) => - dispatch({ type: APP_LOAD, payload, token, skipTracking: true }), - onRedirect: () => dispatch({ type: REDIRECT }), -}); - -const App = (props) => { - const { redirectTo, onRedirect, onLoad } = props; - const navigate = useNavigate(); - - useEffect(() => { - if (redirectTo) { - navigate(redirectTo); - onRedirect(); - } - }, [redirectTo, onRedirect, navigate]); - - useEffect(() => { - const token = window.localStorage.getItem("jwt"); - if (token) { - agent.setToken(token); - } - onLoad(token ? agent.Auth.current() : null, token); - }, [onLoad]); - - if (props.appLoaded) { - return ( -
-
- - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - -
- ); - } - return ( -
-
-
- ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(App); \ No newline at end of file diff --git a/.framework/react/frontend/src/components/Editor.js b/.framework/react/frontend/src/components/Editor.js deleted file mode 100644 index 700a401..0000000 --- a/.framework/react/frontend/src/components/Editor.js +++ /dev/null @@ -1,176 +0,0 @@ -import ListErrors from "./ListErrors"; -import React from "react"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { - ADD_TAG, - EDITOR_PAGE_LOADED, - REMOVE_TAG, - ITEM_SUBMITTED, - EDITOR_PAGE_UNLOADED, - UPDATE_FIELD_EDITOR, -} from "../constants/actionTypes"; -import { withRouterParams } from "./commons"; - -const mapStateToProps = (state) => ({ - ...state.editor, -}); - -const mapDispatchToProps = (dispatch) => ({ - onAddTag: () => dispatch({ type: ADD_TAG }), - onLoad: (payload) => dispatch({ type: EDITOR_PAGE_LOADED, payload }), - onRemoveTag: (tag) => dispatch({ type: REMOVE_TAG, tag }), - onSubmit: (payload) => dispatch({ type: ITEM_SUBMITTED, payload }), - onUnload: (payload) => dispatch({ type: EDITOR_PAGE_UNLOADED }), - onUpdateField: (key, value) => - dispatch({ type: UPDATE_FIELD_EDITOR, key, value }), -}); - -class Editor extends React.Component { - constructor() { - super(); - - const updateFieldEvent = (key) => (ev) => - this.props.onUpdateField(key, ev.target.value); - this.changeTitle = updateFieldEvent("title"); - this.changeDescription = updateFieldEvent("description"); - this.changeImage = updateFieldEvent("image"); - this.changeTagInput = updateFieldEvent("tagInput"); - - this.watchForEnter = (ev) => { - if (ev.keyCode === 13) { - ev.preventDefault(); - this.props.onAddTag(); - } - }; - - this.removeTagHandler = (tag) => () => { - this.props.onRemoveTag(tag); - }; - - this.submitForm = (ev) => { - ev.preventDefault(); - const item = { - title: this.props.title, - description: this.props.description, - image: this.props.image, - tagList: this.props.tagList, - }; - - const slug = { slug: this.props.itemSlug }; - const promise = this.props.itemSlug - ? agent.Items.update(Object.assign(item, slug)) - : agent.Items.create(item); - - this.props.onSubmit(promise); - }; - } - - componentDidUpdate(prevProps) { - if (this.props.params.slug !== prevProps.params.slug) { - if (this.props.params.slug) { - this.props.onUnload(); - return this.props.onLoad(agent.Items.get(this.props.params.slug)); - } - this.props.onLoad(null); - } - } - - componentDidMount() { - if (this.props.params.slug) { - return this.props.onLoad(agent.Items.get(this.props.params.slug)); - } - this.props.onLoad(null); - } - - componentWillUnmount() { - this.props.onUnload(); - } - - render() { - return ( -
-
-
-
- - -
-
-
- -
- -
- -
- -
- -
- -
- - -
- {(this.props.tagList || []).map((tag) => { - return ( - - - {tag} - - ); - })} -
-
- - -
-
-
-
-
-
- ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(withRouterParams(Editor)); diff --git a/.framework/react/frontend/src/components/Header.js b/.framework/react/frontend/src/components/Header.js deleted file mode 100644 index be37dfc..0000000 --- a/.framework/react/frontend/src/components/Header.js +++ /dev/null @@ -1,73 +0,0 @@ -import React from "react"; -import { Link } from "react-router-dom"; -import logo from "../imgs/topbar_logo.png"; - -const LoggedOutView = () => { - return ( -
    -
  • - - Sign in - -
  • - -
  • - - Sign up - -
  • -
- ); -}; - -const LoggedInView = (props) => { - return ( -
    -
  • - -  New Item - -
  • - -
  • - -  Settings - -
  • - -
  • - - {props.currentUser.username} - {props.currentUser.username} - -
  • -
- ); -}; - -class Header extends React.Component { - render() { - return ( - - ); - } -} - -export default Header; diff --git a/.framework/react/frontend/src/components/Home/Banner.js b/.framework/react/frontend/src/components/Home/Banner.js deleted file mode 100644 index 60eed20..0000000 --- a/.framework/react/frontend/src/components/Home/Banner.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react"; -import logo from "../../imgs/logo.png"; - -const Banner = () => { - return ( -
-
- -
- A place to - get - the cool stuff. -
-
-
- ); -}; - -export default Banner; diff --git a/.framework/react/frontend/src/components/Home/MainView.js b/.framework/react/frontend/src/components/Home/MainView.js deleted file mode 100644 index bf92549..0000000 --- a/.framework/react/frontend/src/components/Home/MainView.js +++ /dev/null @@ -1,100 +0,0 @@ -import ItemList from "../ItemList"; -import React from "react"; -import agent from "../../agent"; -import { connect } from "react-redux"; -import { CHANGE_TAB } from "../../constants/actionTypes"; - -const YourFeedTab = (props) => { - if (props.token) { - const clickHandler = (ev) => { - ev.preventDefault(); - props.onTabClick("feed", agent.Items.feed, agent.Items.feed()); - }; - - return ( -
  • - -
  • - ); - } - return null; -}; - -const GlobalFeedTab = (props) => { - const clickHandler = (ev) => { - ev.preventDefault(); - props.onTabClick("all", agent.Items.all, agent.Items.all()); - }; - return ( -
  • - -
  • - ); -}; - -const TagFilterTab = (props) => { - if (!props.tag) { - return null; - } - - return ( -
  • - -
  • - ); -}; - -const mapStateToProps = (state) => ({ - ...state.itemList, - tags: state.home.tags, - token: state.common.token, -}); - -const mapDispatchToProps = (dispatch) => ({ - onTabClick: (tab, pager, payload) => - dispatch({ type: CHANGE_TAB, tab, pager, payload }), -}); - -const MainView = (props) => { - return ( -
    -
    -
      - - - - - -
    -
    - - -
    - ); -}; - -export default connect(mapStateToProps, mapDispatchToProps)(MainView); diff --git a/.framework/react/frontend/src/components/Home/Tags.js b/.framework/react/frontend/src/components/Home/Tags.js deleted file mode 100644 index 01cba5d..0000000 --- a/.framework/react/frontend/src/components/Home/Tags.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import agent from "../../agent"; - -const Tags = (props) => { - const tags = props.tags; - if (tags) { - return ( -
    - Popular tags: - - {tags.map((tag) => { - const handleClick = (ev) => { - ev.preventDefault(); - props.onClickTag( - tag, - (page) => agent.Items.byTag(tag, page), - agent.Items.byTag(tag) - ); - }; - - return ( - - ); - })} - -
    - ); - } else { - return
    Loading Tags...
    ; - } -}; - -export default Tags; diff --git a/.framework/react/frontend/src/components/Home/index.js b/.framework/react/frontend/src/components/Home/index.js deleted file mode 100644 index 34e09ae..0000000 --- a/.framework/react/frontend/src/components/Home/index.js +++ /dev/null @@ -1,54 +0,0 @@ -import Banner from "./Banner"; -import MainView from "./MainView"; -import React, { useEffect } from "react"; -import Tags from "./Tags"; -import agent from "../../agent"; -import { connect } from "react-redux"; -import { - HOME_PAGE_LOADED, - HOME_PAGE_UNLOADED, - APPLY_TAG_FILTER, -} from "../../constants/actionTypes"; - -const Promise = global.Promise; - -const mapStateToProps = (state) => ({ - ...state.home, - appName: state.common.appName, - token: state.common.token, -}); - -const mapDispatchToProps = (dispatch) => ({ - onClickTag: (tag, pager, payload) => - dispatch({ type: APPLY_TAG_FILTER, tag, pager, payload }), - onLoad: (tab, pager, payload) => - dispatch({ type: HOME_PAGE_LOADED, tab, pager, payload }), - onUnload: () => dispatch({ type: HOME_PAGE_UNLOADED }), -}); - -const Home = ({onLoad, onUnload, tags, onClickTag}) => { - const tab = "all"; - const itemsPromise = agent.Items.all; - - useEffect(() => { - onLoad( - tab, - itemsPromise, - Promise.all([agent.Tags.getAll(), itemsPromise()]) - ); - return onUnload; - }, [onLoad, onUnload, tab, itemsPromise]); - - return ( -
    - - -
    - - -
    -
    - ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(Home); \ No newline at end of file diff --git a/.framework/react/frontend/src/components/Item/Comment.js b/.framework/react/frontend/src/components/Item/Comment.js deleted file mode 100644 index f852408..0000000 --- a/.framework/react/frontend/src/components/Item/Comment.js +++ /dev/null @@ -1,42 +0,0 @@ -import DeleteButton from "./DeleteButton"; -import { Link } from "react-router-dom"; -import React from "react"; - -const Comment = (props) => { - const comment = props.comment; - const show = - props.currentUser && props.currentUser.username === comment.seller.username; - return ( -
    -
    -
    -

    {comment.body}

    -
    - - {comment.seller.username} - -   - - {comment.seller.username} - - | - - {new Date(comment.createdAt).toDateString()} - - -
    -
    -
    -
    - ); -}; - -export default Comment; diff --git a/.framework/react/frontend/src/components/Item/CommentContainer.js b/.framework/react/frontend/src/components/Item/CommentContainer.js deleted file mode 100644 index 88562b4..0000000 --- a/.framework/react/frontend/src/components/Item/CommentContainer.js +++ /dev/null @@ -1,46 +0,0 @@ -import CommentInput from "./CommentInput"; -import CommentList from "./CommentList"; -import { Link } from "react-router-dom"; -import React from "react"; - -const CommentContainer = (props) => { - if (props.currentUser) { - return ( -
    - -
    -
    - - -
    -
    -
    - ); - } else { - return ( -
    - -

    - - Sign in - -  or  - - sign up - -  to add comments on this item. -

    -
    - ); - } -}; - -export default CommentContainer; diff --git a/.framework/react/frontend/src/components/Item/CommentInput.js b/.framework/react/frontend/src/components/Item/CommentInput.js deleted file mode 100644 index 250a241..0000000 --- a/.framework/react/frontend/src/components/Item/CommentInput.js +++ /dev/null @@ -1,59 +0,0 @@ -import React from "react"; -import agent from "../../agent"; -import { connect } from "react-redux"; -import { ADD_COMMENT } from "../../constants/actionTypes"; - -const mapDispatchToProps = (dispatch) => ({ - onSubmit: (payload) => dispatch({ type: ADD_COMMENT, payload }), -}); - -class CommentInput extends React.Component { - constructor() { - super(); - this.state = { - body: "", - }; - - this.setBody = (ev) => { - this.setState({ body: ev.target.value }); - }; - - this.createComment = async (ev) => { - ev.preventDefault(); - agent.Comments.create(this.props.slug, { - body: this.state.body, - }).then((payload) => { - this.props.onSubmit(payload); - }); - this.setState({ body: "" }); - }; - } - - render() { - return ( -
    -
    - -
    -
    - {this.props.currentUser.username} - -
    -
    - ); - } -} - -export default connect(() => ({}), mapDispatchToProps)(CommentInput); diff --git a/.framework/react/frontend/src/components/Item/CommentList.js b/.framework/react/frontend/src/components/Item/CommentList.js deleted file mode 100644 index b1bcb35..0000000 --- a/.framework/react/frontend/src/components/Item/CommentList.js +++ /dev/null @@ -1,21 +0,0 @@ -import Comment from "./Comment"; -import React from "react"; - -const CommentList = (props) => { - return ( -
    - {props.comments.map((comment) => { - return ( - - ); - })} -
    - ); -}; - -export default CommentList; diff --git a/.framework/react/frontend/src/components/Item/DeleteButton.js b/.framework/react/frontend/src/components/Item/DeleteButton.js deleted file mode 100644 index b78b1b2..0000000 --- a/.framework/react/frontend/src/components/Item/DeleteButton.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from "react"; -import agent from "../../agent"; -import { connect } from "react-redux"; -import { DELETE_COMMENT } from "../../constants/actionTypes"; - -const mapDispatchToProps = (dispatch) => ({ - onClick: (payload, commentId) => - dispatch({ type: DELETE_COMMENT, payload, commentId }), -}); - -const DeleteButton = (props) => { - const del = () => { - const payload = agent.Comments.delete(props.slug, props.commentId); - props.onClick(payload, props.commentId); - }; - - if (props.show) { - return ( - - - - ); - } - return null; -}; - -export default connect(() => ({}), mapDispatchToProps)(DeleteButton); diff --git a/.framework/react/frontend/src/components/Item/ItemActions.js b/.framework/react/frontend/src/components/Item/ItemActions.js deleted file mode 100644 index b6d8615..0000000 --- a/.framework/react/frontend/src/components/Item/ItemActions.js +++ /dev/null @@ -1,36 +0,0 @@ -import { Link } from "react-router-dom"; -import React from "react"; -import agent from "../../agent"; -import { connect } from "react-redux"; -import { DELETE_ITEM } from "../../constants/actionTypes"; - -const mapDispatchToProps = (dispatch) => ({ - onClickDelete: (payload) => dispatch({ type: DELETE_ITEM, payload }), -}); - -const ItemActions = (props) => { - const item = props.item; - const del = () => { - props.onClickDelete(agent.Items.del(item.slug)); - }; - if (props.canModify) { - return ( - - - Edit Item - - - - - ); - } - - return ; -}; - -export default connect(() => ({}), mapDispatchToProps)(ItemActions); diff --git a/.framework/react/frontend/src/components/Item/ItemMeta.js b/.framework/react/frontend/src/components/Item/ItemMeta.js deleted file mode 100644 index c3bdb6e..0000000 --- a/.framework/react/frontend/src/components/Item/ItemMeta.js +++ /dev/null @@ -1,30 +0,0 @@ -import ItemActions from "./ItemActions"; -import { Link } from "react-router-dom"; -import React from "react"; - -const ItemMeta = (props) => { - const item = props.item; - return ( -
    - - {item.seller.username} - - -
    - - {item.seller.username} - - {new Date(item.createdAt).toDateString()} -
    - - -
    - ); -}; - -export default ItemMeta; diff --git a/.framework/react/frontend/src/components/Item/index.js b/.framework/react/frontend/src/components/Item/index.js deleted file mode 100644 index 7d1bf58..0000000 --- a/.framework/react/frontend/src/components/Item/index.js +++ /dev/null @@ -1,85 +0,0 @@ -import ItemMeta from "./ItemMeta"; -import CommentContainer from "./CommentContainer"; -import React, { useEffect } from "react"; -import { connect } from "react-redux"; -import marked from "marked"; -import { - ITEM_PAGE_LOADED, - ITEM_PAGE_UNLOADED, -} from "../../constants/actionTypes"; -import { getItemAndComments } from "./utils/ItemFetcher"; -import { useParams } from "react-router-dom"; - -const mapStateToProps = (state) => ({ - ...state.item, - currentUser: state.common.currentUser, -}); - -const mapDispatchToProps = (dispatch) => ({ - onLoad: (payload) => dispatch({ type: ITEM_PAGE_LOADED, payload }), - onUnload: () => dispatch({ type: ITEM_PAGE_UNLOADED }), -}); - -const Item = (props) => { - const params = useParams(); - const {onLoad, onUnload} = props; - useEffect(() => { - getItemAndComments( - params.id - ).then(([item, comments]) => { - onLoad([item, comments]); - }); - return onUnload; - }, [onLoad, onUnload, params]); - - if (!props.item) { - return null; - } - - const markup = { - __html: marked(props.item.description, { sanitize: true }), - }; - const canModify = - props.currentUser && - props.currentUser.username === props.item.seller.username; - return ( -
    -
    -
    -
    - {props.item.title} -
    - -
    -

    {props.item.title}

    - -
    - {props.item.tagList.map((tag) => { - return ( - - {tag} - - ); - })} -
    -
    - -
    - -
    -
    -
    - ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(Item); diff --git a/.framework/react/frontend/src/components/Item/utils/ItemFetcher.js b/.framework/react/frontend/src/components/Item/utils/ItemFetcher.js deleted file mode 100644 index 6ebd6c8..0000000 --- a/.framework/react/frontend/src/components/Item/utils/ItemFetcher.js +++ /dev/null @@ -1,8 +0,0 @@ -import agent from "../../../agent"; - -export async function getItemAndComments(id) { - const item = await agent.Items.get(id); - const comments = await agent.Comments.forItem(id); - - return [item, comments]; -} diff --git a/.framework/react/frontend/src/components/ItemList.js b/.framework/react/frontend/src/components/ItemList.js deleted file mode 100644 index 268714e..0000000 --- a/.framework/react/frontend/src/components/ItemList.js +++ /dev/null @@ -1,35 +0,0 @@ -import ItemPreview from "./ItemPreview"; -import ListPagination from "./ListPagination"; -import React from "react"; - -const ItemList = (props) => { - if (!props.items) { - return
    Loading...
    ; - } - - if (props.items.length === 0) { - return
    No items are here... yet.
    ; - } - - return ( -
    -
    - {props.items.map((item) => { - return ( -
    - -
    - ); - })} -
    - - -
    - ); -}; - -export default ItemList; diff --git a/.framework/react/frontend/src/components/ItemPreview.js b/.framework/react/frontend/src/components/ItemPreview.js deleted file mode 100644 index ce89b00..0000000 --- a/.framework/react/frontend/src/components/ItemPreview.js +++ /dev/null @@ -1,66 +0,0 @@ -import React from "react"; -import { Link } from "react-router-dom"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { ITEM_FAVORITED, ITEM_UNFAVORITED } from "../constants/actionTypes"; - -const mapDispatchToProps = (dispatch) => ({ - favorite: (slug) => - dispatch({ - type: ITEM_FAVORITED, - payload: agent.Items.favorite(slug), - }), - unfavorite: (slug) => - dispatch({ - type: ITEM_UNFAVORITED, - payload: agent.Items.unfavorite(slug), - }), -}); - -const ItemPreview = (props) => { - const item = props.item; - - const handleClick = (ev) => { - ev.preventDefault(); - if (item.favorited) { - props.unfavorite(item.slug); - } else { - props.favorite(item.slug); - } - }; - - return ( -
    - item -
    - -

    {item.title}

    -

    {item.description}

    - -
    - - {item.seller.username} - - -
    -
    -
    - ); -}; - -export default connect(() => ({}), mapDispatchToProps)(ItemPreview); diff --git a/.framework/react/frontend/src/components/ListErrors.js b/.framework/react/frontend/src/components/ListErrors.js deleted file mode 100644 index 33c97e8..0000000 --- a/.framework/react/frontend/src/components/ListErrors.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; - -class ListErrors extends React.Component { - render() { - const errors = this.props.errors; - if (errors) { - return ( -
      - {Object.keys(errors).map((key) => { - return ( -
    • - {key} {errors[key]} -
    • - ); - })} -
    - ); - } else { - return null; - } - } -} - -export default ListErrors; diff --git a/.framework/react/frontend/src/components/ListPagination.js b/.framework/react/frontend/src/components/ListPagination.js deleted file mode 100644 index fcefbcc..0000000 --- a/.framework/react/frontend/src/components/ListPagination.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from "react"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { SET_PAGE } from "../constants/actionTypes"; - -const mapDispatchToProps = (dispatch) => ({ - onSetPage: (page, payload) => dispatch({ type: SET_PAGE, page, payload }), -}); - -const ListPagination = (props) => { - if (props.itemsCount <= 10) { - return null; - } - - const range = []; - for (let i = 0; i < Math.ceil(props.itemsCount / 10); ++i) { - range.push(i); - } - - const setPage = (page) => { - if (props.pager) { - props.onSetPage(page, props.pager(page)); - } else { - props.onSetPage(page, agent.Items.all(page)); - } - }; - - return ( - - ); -}; - -export default connect(() => ({}), mapDispatchToProps)(ListPagination); diff --git a/.framework/react/frontend/src/components/Login.js b/.framework/react/frontend/src/components/Login.js deleted file mode 100644 index af4f12d..0000000 --- a/.framework/react/frontend/src/components/Login.js +++ /dev/null @@ -1,121 +0,0 @@ -import { Link } from "react-router-dom"; -import ListErrors from "./ListErrors"; -import React from "react"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { - UPDATE_FIELD_AUTH, - LOGIN, - LOGIN_PAGE_UNLOADED, -} from "../constants/actionTypes"; - -const mapStateToProps = (state) => ({ ...state.auth }); - -const mapDispatchToProps = (dispatch) => ({ - onChangeEmail: (value) => - dispatch({ type: UPDATE_FIELD_AUTH, key: "email", value }), - onChangePassword: (value) => - dispatch({ type: UPDATE_FIELD_AUTH, key: "password", value }), - onSubmit: (email, password) => - dispatch({ type: LOGIN, payload: agent.Auth.login(email, password) }), - onUnload: () => dispatch({ type: LOGIN_PAGE_UNLOADED }), -}); - -class Login extends React.Component { - constructor() { - super(); - this.changeEmail = (ev) => this.props.onChangeEmail(ev.target.value); - this.changePassword = (ev) => this.props.onChangePassword(ev.target.value); - this.submitForm = (email, password) => (ev) => { - ev.preventDefault(); - this.props.onSubmit(email, password); - }; - } - - componentWillUnmount() { - this.props.onUnload(); - } - - render() { - const email = this.props.email; - const password = this.props.password; - return ( -
    -
    -
    -
    -

    Sign In

    - - - -
    -
    -
    -
    -
    - - - -
    - -
    -
    - -
    -
    -
    - - - -
    - -
    -
    - - -
    -
    -

    - - Need an account? - -

    -
    -
    -
    -
    - ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(Login); diff --git a/.framework/react/frontend/src/components/Profile.js b/.framework/react/frontend/src/components/Profile.js deleted file mode 100644 index b2e0f0b..0000000 --- a/.framework/react/frontend/src/components/Profile.js +++ /dev/null @@ -1,172 +0,0 @@ -import ItemList from "./ItemList"; -import React from "react"; -import { Link } from "react-router-dom"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { - FOLLOW_USER, - UNFOLLOW_USER, - PROFILE_PAGE_LOADED, - PROFILE_PAGE_UNLOADED, -} from "../constants/actionTypes"; -import { withRouterParams } from "./commons"; - -const EditProfileSettings = (props) => { - if (props.isUser) { - return ( - - Edit Profile Settings - - ); - } - return null; -}; - -const FollowUserButton = (props) => { - if (props.isUser) { - return null; - } - - let classes = "btn btn-sm action-btn"; - if (props.user.following) { - classes += " btn-secondary"; - } else { - classes += " btn-outline-secondary"; - } - - const handleClick = (ev) => { - ev.preventDefault(); - if (props.user.following) { - props.unfollow(props.user.username); - } else { - props.follow(props.user.username); - } - }; - - return ( - - ); -}; - -const mapStateToProps = (state) => ({ - ...state.itemList, - currentUser: state.common.currentUser, - profile: state.profile, -}); - -const mapDispatchToProps = (dispatch) => ({ - onFollow: (username) => - dispatch({ - type: FOLLOW_USER, - payload: agent.Profile.follow(username), - }), - onLoad: (payload) => dispatch({ type: PROFILE_PAGE_LOADED, payload }), - onUnfollow: (username) => - dispatch({ - type: UNFOLLOW_USER, - payload: agent.Profile.unfollow(username), - }), - onUnload: () => dispatch({ type: PROFILE_PAGE_UNLOADED }), -}); - -class Profile extends React.Component { - componentDidMount() { - const username = this.props.params.username?.substring(1); - this.props.onLoad( - Promise.all([ - agent.Profile.get(username), - agent.Items.bySeller(username), - ]) - ); - } - - componentWillUnmount() { - this.props.onUnload(); - } - - renderTabs() { - return ( -
      -
    • - - My Items - -
    • - -
    • - - Favorited Items - -
    • -
    - ); - } - - render() { - const profile = this.props.profile; - if (!profile) { - return null; - } - - const isUser = - this.props.currentUser && - this.props.profile.username === this.props.currentUser.username; - - return ( -
    -
    -
    -
    - {profile.username} -

    {profile.username}

    -

    {profile.bio}

    - - - -
    -
    -
    - -
    -
    -
    -
    {this.renderTabs()}
    - - -
    -
    -
    -
    - ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(withRouterParams(Profile)); -export { Profile, mapStateToProps }; diff --git a/.framework/react/frontend/src/components/ProfileFavorites.js b/.framework/react/frontend/src/components/ProfileFavorites.js deleted file mode 100644 index 5fd3fba..0000000 --- a/.framework/react/frontend/src/components/ProfileFavorites.js +++ /dev/null @@ -1,56 +0,0 @@ -import { Profile, mapStateToProps } from "./Profile"; -import React from "react"; -import { Link } from "react-router-dom"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { - PROFILE_PAGE_LOADED, - PROFILE_PAGE_UNLOADED, -} from "../constants/actionTypes"; -import { withRouterParams } from "./commons"; - -const mapDispatchToProps = (dispatch) => ({ - onLoad: (pager, payload) => - dispatch({ type: PROFILE_PAGE_LOADED, pager, payload }), - onUnload: () => dispatch({ type: PROFILE_PAGE_UNLOADED }), -}); - -class ProfileFavorites extends Profile { - componentDidMount() { - const username = this.props.params.username?.substring(1); - this.props.onLoad( - (page) => agent.Items.favoritedBy(username, page), - Promise.all([ - agent.Profile.get(username), - agent.Items.favoritedBy(username), - ]) - ); - } - - componentWillUnmount() { - this.props.onUnload(); - } - - renderTabs() { - return ( -
      -
    • - - My Items - -
    • - -
    • - - Favorited Items - -
    • -
    - ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(withRouterParams(ProfileFavorites)); diff --git a/.framework/react/frontend/src/components/Register.js b/.framework/react/frontend/src/components/Register.js deleted file mode 100644 index 195a25a..0000000 --- a/.framework/react/frontend/src/components/Register.js +++ /dev/null @@ -1,148 +0,0 @@ -import { Link } from "react-router-dom"; -import ListErrors from "./ListErrors"; -import React from "react"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { - UPDATE_FIELD_AUTH, - REGISTER, - REGISTER_PAGE_UNLOADED, -} from "../constants/actionTypes"; - -const mapStateToProps = (state) => ({ ...state.auth }); - -const mapDispatchToProps = (dispatch) => ({ - onChangeEmail: (value) => - dispatch({ type: UPDATE_FIELD_AUTH, key: "email", value }), - onChangePassword: (value) => - dispatch({ type: UPDATE_FIELD_AUTH, key: "password", value }), - onChangeUsername: (value) => - dispatch({ type: UPDATE_FIELD_AUTH, key: "username", value }), - onSubmit: (username, email, password) => { - const payload = agent.Auth.register(username, email, password); - dispatch({ type: REGISTER, payload }); - }, - onUnload: () => dispatch({ type: REGISTER_PAGE_UNLOADED }), -}); - -class Register extends React.Component { - constructor() { - super(); - this.changeEmail = (ev) => this.props.onChangeEmail(ev.target.value); - this.changePassword = (ev) => this.props.onChangePassword(ev.target.value); - this.changeUsername = (ev) => this.props.onChangeUsername(ev.target.value); - this.submitForm = (username, email, password) => (ev) => { - ev.preventDefault(); - this.props.onSubmit(username, email, password); - }; - } - - componentWillUnmount() { - this.props.onUnload(); - } - - render() { - const email = this.props.email; - const password = this.props.password; - const username = this.props.username; - - return ( -
    -
    -
    -
    -

    Sign Up

    - - - -
    -
    -
    -
    -
    - - - -
    - -
    -
    - -
    -
    -
    - - - -
    - -
    -
    - -
    -
    -
    - - - -
    - -
    -
    - - -
    -
    -

    - - Have an account? - -

    -
    -
    -
    -
    - ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(Register); diff --git a/.framework/react/frontend/src/components/Settings.js b/.framework/react/frontend/src/components/Settings.js deleted file mode 100644 index e4791bc..0000000 --- a/.framework/react/frontend/src/components/Settings.js +++ /dev/null @@ -1,142 +0,0 @@ -import ListErrors from "./ListErrors"; -import React, { useCallback, useEffect, useState } from "react"; -import agent from "../agent"; -import { connect } from "react-redux"; -import { - SETTINGS_SAVED, - SETTINGS_PAGE_UNLOADED, - LOGOUT, -} from "../constants/actionTypes"; - -const SettingsForm = ({ currentUser, onSubmitForm }) => { - const [user, setUser] = useState({}); - - useEffect(() => { - if (currentUser) { - setUser(currentUser); - } - }, [currentUser]); - - const updateState = useCallback((field) => (ev) => { - const newState = Object.assign({}, user, { [field]: ev.target.value }); - setUser(newState); - }, [user]); - - const submitForm = useCallback((ev) => { - ev.preventDefault(); - const userToSubmit = { ...user }; - if (!userToSubmit.password) { - delete userToSubmit.password; - } - onSubmitForm(userToSubmit); - }, [user, onSubmitForm]); - - return ( -
    -
    -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - -
    - - -
    -
    - ); -} - -const mapStateToProps = (state) => ({ - ...state.settings, - currentUser: state.common.currentUser, -}); - -const mapDispatchToProps = (dispatch) => ({ - onClickLogout: () => dispatch({ type: LOGOUT }), - onSubmitForm: (user) => - dispatch({ type: SETTINGS_SAVED, payload: agent.Auth.save(user) }), - onUnload: () => dispatch({ type: SETTINGS_PAGE_UNLOADED }), -}); - -class Settings extends React.Component { - render() { - return ( -
    -
    -
    -
    -

    Your Settings

    - - - - - -
    - - -
    -
    -
    -
    - ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(Settings); diff --git a/.framework/react/frontend/src/components/commons.js b/.framework/react/frontend/src/components/commons.js deleted file mode 100644 index 8f1fd1c..0000000 --- a/.framework/react/frontend/src/components/commons.js +++ /dev/null @@ -1,5 +0,0 @@ -import { useParams } from "react-router-dom"; - -export function withRouterParams(Component) { - return props => ; -} diff --git a/.framework/react/frontend/src/constants/actionTypes.js b/.framework/react/frontend/src/constants/actionTypes.js deleted file mode 100644 index bb5380b..0000000 --- a/.framework/react/frontend/src/constants/actionTypes.js +++ /dev/null @@ -1,37 +0,0 @@ -export const APP_LOAD = "APP_LOAD"; -export const REDIRECT = "REDIRECT"; -export const ITEM_SUBMITTED = "ITEM_SUBMITTED"; -export const SETTINGS_SAVED = "SETTINGS_SAVED"; -export const DELETE_ITEM = "DELETE_ITEM"; -export const SETTINGS_PAGE_UNLOADED = "SETTINGS_PAGE_UNLOADED"; -export const HOME_PAGE_LOADED = "HOME_PAGE_LOADED"; -export const HOME_PAGE_UNLOADED = "HOME_PAGE_UNLOADED"; -export const ITEM_PAGE_LOADED = "ITEM_PAGE_LOADED"; -export const ITEM_PAGE_UNLOADED = "ITEM_PAGE_UNLOADED"; -export const ADD_COMMENT = "ADD_COMMENT"; -export const DELETE_COMMENT = "DELETE_COMMENT"; -export const ITEM_FAVORITED = "ITEM_FAVORITED"; -export const ITEM_UNFAVORITED = "ITEM_UNFAVORITED"; -export const SET_PAGE = "SET_PAGE"; -export const APPLY_TAG_FILTER = "APPLY_TAG_FILTER"; -export const CHANGE_TAB = "CHANGE_TAB"; -export const PROFILE_PAGE_LOADED = "PROFILE_PAGE_LOADED"; -export const PROFILE_PAGE_UNLOADED = "PROFILE_PAGE_UNLOADED"; -export const LOGIN = "LOGIN"; -export const LOGOUT = "LOGOUT"; -export const REGISTER = "REGISTER"; -export const LOGIN_PAGE_UNLOADED = "LOGIN_PAGE_UNLOADED"; -export const REGISTER_PAGE_UNLOADED = "REGISTER_PAGE_UNLOADED"; -export const ASYNC_START = "ASYNC_START"; -export const ASYNC_END = "ASYNC_END"; -export const EDITOR_PAGE_LOADED = "EDITOR_PAGE_LOADED"; -export const EDITOR_PAGE_UNLOADED = "EDITOR_PAGE_UNLOADED"; -export const ADD_TAG = "ADD_TAG"; -export const REMOVE_TAG = "REMOVE_TAG"; -export const UPDATE_FIELD_AUTH = "UPDATE_FIELD_AUTH"; -export const UPDATE_FIELD_EDITOR = "UPDATE_FIELD_EDITOR"; -export const FOLLOW_USER = "FOLLOW_USER"; -export const UNFOLLOW_USER = "UNFOLLOW_USER"; -export const PROFILE_FAVORITES_PAGE_UNLOADED = - "PROFILE_FAVORITES_PAGE_UNLOADED"; -export const PROFILE_FAVORITES_PAGE_LOADED = "PROFILE_FAVORITES_PAGE_LOADED"; diff --git a/.framework/react/frontend/src/custom.scss b/.framework/react/frontend/src/custom.scss deleted file mode 100644 index 0b4d757..0000000 --- a/.framework/react/frontend/src/custom.scss +++ /dev/null @@ -1,61 +0,0 @@ -@import url("https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700,800"); - -// Override default variables before the import -$primary: #2b1456; -$secondary: #ff2b98; - -$body-color: white; //this is the text color -$body-bg: $primary; - -$dark: #170539; -$light: #af93f2; - -$input-border-color: #d0d0d0; - -$font-family-base: "Poppins", sans-serif !important; - -$theme-colors: ( - "light-gray": #f2f2f2, -); - -// Import Bootstrap and its default variables -@import "~bootstrap/scss/bootstrap.scss"; -@import "~bootstrap-icons/font/bootstrap-icons.css"; - -body { - background-image: url("./imgs/background.png"); - background-position: top; - background-repeat: no-repeat; -} -.page { - margin-top: 2 * $spacer; - margin-bottom: 2 * $spacer; -} - -.user-pic { - height: 40px; - width: 40px; -} - -.user-img { - width: 100px; - height: 100px; - border-radius: 100px; -} - -.item-img { - height: 150px; - object-fit: cover; -} - -.crop-text-3 { - -webkit-line-clamp: 3; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-box-orient: vertical; -} - -.user-info { - min-width: 800px; -} diff --git a/.framework/react/frontend/src/imgs/background.png b/.framework/react/frontend/src/imgs/background.png deleted file mode 100644 index 6c2e0f9..0000000 Binary files a/.framework/react/frontend/src/imgs/background.png and /dev/null differ diff --git a/.framework/react/frontend/src/imgs/logo.png b/.framework/react/frontend/src/imgs/logo.png deleted file mode 100644 index 89757c2..0000000 Binary files a/.framework/react/frontend/src/imgs/logo.png and /dev/null differ diff --git a/.framework/react/frontend/src/imgs/topbar_logo.png b/.framework/react/frontend/src/imgs/topbar_logo.png deleted file mode 100644 index e7fefd3..0000000 Binary files a/.framework/react/frontend/src/imgs/topbar_logo.png and /dev/null differ diff --git a/.framework/react/frontend/src/index.js b/.framework/react/frontend/src/index.js deleted file mode 100644 index a6ecd9b..0000000 --- a/.framework/react/frontend/src/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import "./custom.scss"; -import ReactDOM from "react-dom"; -import { Provider } from "react-redux"; -import React from "react"; -import { store } from "./store"; - -import App from "./components/App"; -import { BrowserRouter } from "react-router-dom"; - -ReactDOM.render( - - - - - , - - document.getElementById("root") -); diff --git a/.framework/react/frontend/src/middleware.js b/.framework/react/frontend/src/middleware.js deleted file mode 100644 index 4f82efb..0000000 --- a/.framework/react/frontend/src/middleware.js +++ /dev/null @@ -1,65 +0,0 @@ -import agent from "./agent"; -import { - ASYNC_START, - ASYNC_END, - LOGIN, - LOGOUT, - REGISTER, -} from "./constants/actionTypes"; - -const promiseMiddleware = (store) => (next) => (action) => { - if (isPromise(action.payload)) { - store.dispatch({ type: ASYNC_START, subtype: action.type }); - - const currentView = store.getState().viewChangeCounter; - const skipTracking = action.skipTracking; - - action.payload.then( - (res) => { - const currentState = store.getState(); - if (!skipTracking && currentState.viewChangeCounter !== currentView) { - return; - } - action.payload = res; - store.dispatch({ type: ASYNC_END, promise: action.payload }); - store.dispatch(action); - }, - (error) => { - const currentState = store.getState(); - if (!skipTracking && currentState.viewChangeCounter !== currentView) { - return; - } - action.error = true; - action.payload = error.response.body; - if (!action.skipTracking) { - store.dispatch({ type: ASYNC_END, promise: action.payload }); - } - store.dispatch(action); - } - ); - - return; - } - - next(action); -}; - -const localStorageMiddleware = (store) => (next) => (action) => { - if (action.type === REGISTER || action.type === LOGIN) { - if (!action.error) { - window.localStorage.setItem("jwt", action.payload.user.token); - agent.setToken(action.payload.user.token); - } - } else if (action.type === LOGOUT) { - window.localStorage.setItem("jwt", ""); - agent.setToken(null); - } - - next(action); -}; - -function isPromise(v) { - return v && typeof v.then === "function"; -} - -export { promiseMiddleware, localStorageMiddleware }; diff --git a/.framework/react/frontend/src/reducer.js b/.framework/react/frontend/src/reducer.js deleted file mode 100644 index 65173ca..0000000 --- a/.framework/react/frontend/src/reducer.js +++ /dev/null @@ -1,20 +0,0 @@ -import item from "./reducers/item"; -import itemList from "./reducers/itemList"; -import auth from "./reducers/auth"; -import { combineReducers } from "redux"; -import common from "./reducers/common"; -import editor from "./reducers/editor"; -import home from "./reducers/home"; -import profile from "./reducers/profile"; -import settings from "./reducers/settings"; - -export default combineReducers({ - item, - itemList, - auth, - common, - editor, - home, - profile, - settings, -}); diff --git a/.framework/react/frontend/src/reducers/auth.js b/.framework/react/frontend/src/reducers/auth.js deleted file mode 100644 index 6128b11..0000000 --- a/.framework/react/frontend/src/reducers/auth.js +++ /dev/null @@ -1,36 +0,0 @@ -import { - LOGIN, - REGISTER, - LOGIN_PAGE_UNLOADED, - REGISTER_PAGE_UNLOADED, - ASYNC_START, - UPDATE_FIELD_AUTH, -} from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case LOGIN: - case REGISTER: - return { - ...state, - inProgress: false, - errors: action.error ? action.payload.errors : null, - }; - case LOGIN_PAGE_UNLOADED: - case REGISTER_PAGE_UNLOADED: - return {}; - case ASYNC_START: - if (action.subtype === LOGIN || action.subtype === REGISTER) { - return { ...state, inProgress: true }; - } - break; - case UPDATE_FIELD_AUTH: - return { ...state, [action.key]: action.value }; - default: - return state; - } - - return state; -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/common.js b/.framework/react/frontend/src/reducers/common.js deleted file mode 100644 index 3ef54b4..0000000 --- a/.framework/react/frontend/src/reducers/common.js +++ /dev/null @@ -1,79 +0,0 @@ -import { - APP_LOAD, - REDIRECT, - LOGOUT, - ITEM_SUBMITTED, - SETTINGS_SAVED, - LOGIN, - REGISTER, - DELETE_ITEM, - ITEM_PAGE_UNLOADED, - EDITOR_PAGE_UNLOADED, - HOME_PAGE_UNLOADED, - PROFILE_PAGE_UNLOADED, - PROFILE_FAVORITES_PAGE_UNLOADED, - SETTINGS_PAGE_UNLOADED, - LOGIN_PAGE_UNLOADED, - REGISTER_PAGE_UNLOADED, -} from "../constants/actionTypes"; - -const defaultState = { - appName: "Anythink Market", - token: null, - viewChangeCounter: 0, -}; - -const reducer = (state = defaultState, action) => { - switch (action.type) { - case APP_LOAD: - return { - ...state, - token: action.token || null, - appLoaded: true, - currentUser: action.payload ? action.payload.user : null, - }; - case REDIRECT: - return { ...state, redirectTo: null }; - case LOGOUT: - return { ...state, redirectTo: "/", token: null, currentUser: null }; - case ITEM_SUBMITTED: { - const redirectUrl = `/item/${action.payload.item.slug}`; - return { ...state, redirectTo: redirectUrl }; - } - case SETTINGS_SAVED: - return { - ...state, - redirectTo: action.error ? null : "/", - currentUser: action.error ? null : action.payload.user, - }; - case LOGIN: - return { - ...state, - redirectTo: action.error ? null : "/", - token: action.error ? null : action.payload.user.token, - currentUser: action.error ? null : action.payload.user, - }; - case REGISTER: - return { - ...state, - redirectTo: action.error ? null : `/@${action.payload.user.username}`, - token: action.error ? null : action.payload.user.token, - currentUser: action.error ? null : action.payload.user, - }; - case DELETE_ITEM: - return { ...state, redirectTo: "/" }; - case ITEM_PAGE_UNLOADED: - case EDITOR_PAGE_UNLOADED: - case HOME_PAGE_UNLOADED: - case PROFILE_PAGE_UNLOADED: - case PROFILE_FAVORITES_PAGE_UNLOADED: - case SETTINGS_PAGE_UNLOADED: - case LOGIN_PAGE_UNLOADED: - case REGISTER_PAGE_UNLOADED: - return { ...state, viewChangeCounter: state.viewChangeCounter + 1 }; - default: - return state; - } -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/editor.js b/.framework/react/frontend/src/reducers/editor.js deleted file mode 100644 index 4320e70..0000000 --- a/.framework/react/frontend/src/reducers/editor.js +++ /dev/null @@ -1,56 +0,0 @@ -import { - EDITOR_PAGE_LOADED, - EDITOR_PAGE_UNLOADED, - ITEM_SUBMITTED, - ASYNC_START, - ADD_TAG, - REMOVE_TAG, - UPDATE_FIELD_EDITOR, -} from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case EDITOR_PAGE_LOADED: - return { - ...state, - itemSlug: action.payload ? action.payload.item.slug : "", - title: action.payload ? action.payload.item.title : "", - description: action.payload ? action.payload.item.description : "", - image: action.payload ? action.payload.item.image : "", - tagInput: "", - tagList: action.payload ? action.payload.item.tagList : [], - }; - case EDITOR_PAGE_UNLOADED: - return {}; - case ITEM_SUBMITTED: - return { - ...state, - inProgress: null, - errors: action.error ? action.payload.errors : null, - }; - case ASYNC_START: - if (action.subtype === ITEM_SUBMITTED) { - return { ...state, inProgress: true }; - } - break; - case ADD_TAG: - return { - ...state, - tagList: state.tagList.concat([state.tagInput]), - tagInput: "", - }; - case REMOVE_TAG: - return { - ...state, - tagList: state.tagList.filter((tag) => tag !== action.tag), - }; - case UPDATE_FIELD_EDITOR: - return { ...state, [action.key]: action.value }; - default: - return state; - } - - return state; -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/home.js b/.framework/react/frontend/src/reducers/home.js deleted file mode 100644 index b9bc097..0000000 --- a/.framework/react/frontend/src/reducers/home.js +++ /dev/null @@ -1,17 +0,0 @@ -import { HOME_PAGE_LOADED, HOME_PAGE_UNLOADED } from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case HOME_PAGE_LOADED: - return { - ...state, - tags: action.payload[0].tags, - }; - case HOME_PAGE_UNLOADED: - return {}; - default: - return state; - } -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/item.js b/.framework/react/frontend/src/reducers/item.js deleted file mode 100644 index 918201c..0000000 --- a/.framework/react/frontend/src/reducers/item.js +++ /dev/null @@ -1,38 +0,0 @@ -import { - ITEM_PAGE_LOADED, - ITEM_PAGE_UNLOADED, - ADD_COMMENT, - DELETE_COMMENT, -} from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case ITEM_PAGE_LOADED: - return { - ...state, - item: action.payload[0].item, - comments: action.payload[1].comments, - }; - case ITEM_PAGE_UNLOADED: - return {}; - case ADD_COMMENT: - return { - ...state, - commentErrors: action.error ? action.payload.errors : null, - comments: action.error - ? null - : (state.comments || []).concat([action.payload.comment]), - }; - case DELETE_COMMENT: { - const commentId = action.commentId; - return { - ...state, - comments: state.comments.filter((comment) => comment.id !== commentId), - }; - } - default: - return state; - } -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/itemList.js b/.framework/react/frontend/src/reducers/itemList.js deleted file mode 100644 index 016a996..0000000 --- a/.framework/react/frontend/src/reducers/itemList.js +++ /dev/null @@ -1,88 +0,0 @@ -import { - ITEM_FAVORITED, - ITEM_UNFAVORITED, - SET_PAGE, - APPLY_TAG_FILTER, - HOME_PAGE_LOADED, - HOME_PAGE_UNLOADED, - CHANGE_TAB, - PROFILE_PAGE_LOADED, - PROFILE_PAGE_UNLOADED, - PROFILE_FAVORITES_PAGE_LOADED, - PROFILE_FAVORITES_PAGE_UNLOADED, -} from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case ITEM_FAVORITED: - case ITEM_UNFAVORITED: - return { - ...state, - items: state.items.map((item) => { - if (item.slug === action.payload.item.slug) { - return { - ...item, - favorited: action.payload.item.favorited, - favoritesCount: action.payload.item.favoritesCount, - }; - } - return item; - }), - }; - case SET_PAGE: - return { - ...state, - items: action.payload.items, - itemsCount: action.payload.itemsCount, - currentPage: action.page, - }; - case APPLY_TAG_FILTER: - return { - ...state, - pager: action.pager, - items: action.payload.items, - itemsCount: action.payload.itemsCount, - tab: null, - tag: action.tag, - currentPage: 0, - }; - case HOME_PAGE_LOADED: - return { - ...state, - pager: action.pager, - tags: action.payload[0].tags, - items: action.payload[1].items, - itemsCount: action.payload[1].itemsCount, - currentPage: 0, - tab: action.tab, - }; - case HOME_PAGE_UNLOADED: - return {}; - case CHANGE_TAB: - return { - ...state, - pager: action.pager, - items: action.payload.items, - itemsCount: action.payload.itemsCount, - tab: action.tab, - currentPage: 0, - tag: null, - }; - case PROFILE_PAGE_LOADED: - case PROFILE_FAVORITES_PAGE_LOADED: - return { - ...state, - pager: action.pager, - items: action.payload?.[1]?.items, - itemsCount: action.payload?.[1]?.itemsCount, - currentPage: 0, - }; - case PROFILE_PAGE_UNLOADED: - case PROFILE_FAVORITES_PAGE_UNLOADED: - return {}; - default: - return state; - } -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/profile.js b/.framework/react/frontend/src/reducers/profile.js deleted file mode 100644 index 5d4fe85..0000000 --- a/.framework/react/frontend/src/reducers/profile.js +++ /dev/null @@ -1,26 +0,0 @@ -import { - PROFILE_PAGE_LOADED, - PROFILE_PAGE_UNLOADED, - FOLLOW_USER, - UNFOLLOW_USER, -} from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case PROFILE_PAGE_LOADED: - return { - ...action.payload?.[0]?.profile, - }; - case PROFILE_PAGE_UNLOADED: - return {}; - case FOLLOW_USER: - case UNFOLLOW_USER: - return { - ...action.payload.profile, - }; - default: - return state; - } -}; - -export default reducer; diff --git a/.framework/react/frontend/src/reducers/settings.js b/.framework/react/frontend/src/reducers/settings.js deleted file mode 100644 index 2cf4da0..0000000 --- a/.framework/react/frontend/src/reducers/settings.js +++ /dev/null @@ -1,27 +0,0 @@ -import { - SETTINGS_SAVED, - SETTINGS_PAGE_UNLOADED, - ASYNC_START, -} from "../constants/actionTypes"; - -const reducer = (state = {}, action) => { - switch (action.type) { - case SETTINGS_SAVED: - return { - ...state, - inProgress: false, - errors: action.error ? action.payload.errors : null, - }; - case SETTINGS_PAGE_UNLOADED: - return {}; - case ASYNC_START: - return { - ...state, - inProgress: true, - }; - default: - return state; - } -}; - -export default reducer; diff --git a/.framework/react/frontend/src/setupTests.js b/.framework/react/frontend/src/setupTests.js deleted file mode 100644 index 0772595..0000000 --- a/.framework/react/frontend/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -import "core-js"; -import { configure } from "enzyme"; -import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; - -configure({ adapter: new Adapter() }); diff --git a/.framework/react/frontend/src/store.js b/.framework/react/frontend/src/store.js deleted file mode 100644 index 5ac25dc..0000000 --- a/.framework/react/frontend/src/store.js +++ /dev/null @@ -1,25 +0,0 @@ -import { applyMiddleware, createStore } from "redux"; -import { composeWithDevTools } from "redux-devtools-extension/developmentOnly"; -import { promiseMiddleware, localStorageMiddleware } from "./middleware"; -import reducer from "./reducer"; - -import { createBrowserHistory } from "history"; - -export const history = createBrowserHistory(); - -const getMiddleware = () => { - if (process.env.NODE_ENV === "production") { - return applyMiddleware( - promiseMiddleware, - localStorageMiddleware - ); - } else { - // Enable additional logging in non-production environments. - return applyMiddleware( - promiseMiddleware, - localStorageMiddleware, - ); - } -}; - -export const store = createStore(reducer, composeWithDevTools(getMiddleware())); diff --git a/.framework/react/frontend/src/tests/components/Header.test.js b/.framework/react/frontend/src/tests/components/Header.test.js deleted file mode 100644 index 592b742..0000000 --- a/.framework/react/frontend/src/tests/components/Header.test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { create } from "react-test-renderer"; -import { mount } from "enzyme"; -import { BrowserRouter as Router } from "react-router-dom"; -import Header from "../../components/Header"; - -describe("Header component", () => { - it("Snapshot testing with no user", () => { - const component = create( - -
    - - ); - let tree = component.toJSON(); - expect(tree).toMatchSnapshot(); - }); - - it("Snapshot testing with user", () => { - const component = create( - -
    - - ); - let tree = component.toJSON(); - expect(tree).toMatchSnapshot(); - }); - - it("Check link to main page", () => { - const header = mount( - -
    - - ); - expect(header.find("Link").first().prop("to")).toEqual("/"); - }); - - it("Render register button when there's no user", () => { - const header = mount( - -
    - - ); - expect(header.find("li > Link").first().text()).toEqual("Sign in"); - }); - - it("Render user name when there's a user", () => { - const user = { username: "user name", image: "image.png" }; - const header = mount( - -
    - - ); - expect(header.find("li > Link").last().text()).toEqual(user.username); - }); -}); diff --git a/.framework/react/frontend/src/tests/components/__snapshots__/Header.test.js.snap b/.framework/react/frontend/src/tests/components/__snapshots__/Header.test.js.snap deleted file mode 100644 index e2509e5..0000000 --- a/.framework/react/frontend/src/tests/components/__snapshots__/Header.test.js.snap +++ /dev/null @@ -1,119 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Header component Snapshot testing with no user 1`] = ` - -`; - -exports[`Header component Snapshot testing with user 1`] = ` - -`; diff --git a/.framework/react/frontend/src/tests/item/CommentInput.test.js b/.framework/react/frontend/src/tests/item/CommentInput.test.js deleted file mode 100644 index ab7fcf5..0000000 --- a/.framework/react/frontend/src/tests/item/CommentInput.test.js +++ /dev/null @@ -1,64 +0,0 @@ -import { create } from "react-test-renderer"; -import { mount } from "enzyme"; -import configureMockStore from "redux-mock-store"; -import CommentInput from "../../components/Item/CommentInput"; -import agent from "../../agent"; -import { ADD_COMMENT } from "../../constants/actionTypes"; - -const mockStore = configureMockStore(); -agent.Comments.create = jest.fn(); - -describe("CommentInput component", () => { - let store; - - beforeEach(() => { - store = mockStore({}); - }); - - it("Snapshot testing with no user", () => { - const component = create( - - ); - let tree = component.toJSON(); - expect(tree).toMatchSnapshot(); - }); - - it("Submit text", () => { - const user = { username: "name", image: "" }; - const component = mount( - - ); - const comment = { id: 1 }; - agent.Comments.create.mockResolvedValue(comment); - - const event = { target: { value: "sometext" } }; - component.find("textarea").simulate("change", event); - component.find("form").simulate("submit"); - - setImmediate(async () => { - expect(store.getActions()).toHaveLength(1); - expect(store.getActions()[0].type).toEqual(ADD_COMMENT); - expect(await store.getActions()[0].payload).toEqual(comment); - }); - }); - - it("Clear text after submit", async () => { - const user = { username: "name", image: "" }; - - const component = mount( - - ); - - const comment = { id: 1 }; - agent.Comments.create.mockResolvedValue(comment); - - const event = { target: { value: "sometext" } }; - component.find("textarea").simulate("change", event); - component.find("form").simulate("submit"); - expect(component.find("textarea").text()).toHaveLength(0); - }); -}); diff --git a/.framework/react/frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap b/.framework/react/frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap deleted file mode 100644 index f739b2c..0000000 --- a/.framework/react/frontend/src/tests/item/__snapshots__/CommentInput.test.js.snap +++ /dev/null @@ -1,35 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CommentInput component Snapshot testing with no user 1`] = ` -
    -
    -