diff --git a/.ci/doc/config.yml b/.ci/doc/config.yml new file mode 100644 index 00000000..cfff0f76 --- /dev/null +++ b/.ci/doc/config.yml @@ -0,0 +1,18 @@ +--- + +snippets: + mount: /mnt + path: 'doc/**/snippets/*.test.yml' + templates: /mnt/.ci/doc/templates + +runners: + default: java + + java: + service: doc-runner-java + path: /var/snippets/java + build: + cmd: cd /mnt && ./gradlew jar + run: + before: timeout 600 bash -c 'until stat /tmp/runner_is_ready && curl -f -s -o /dev/null http://kuzzle:7512/_now; do sleep 1; done' + cmd: /mnt/.ci/doc/test-snippet.sh {{ snippet.source }} diff --git a/.ci/doc/docker-compose.yml b/.ci/doc/docker-compose.yml new file mode 100644 index 00000000..5a2e9223 --- /dev/null +++ b/.ci/doc/docker-compose.yml @@ -0,0 +1,56 @@ +version: '3' + +services: + kuzzle: + image: kuzzleio/kuzzle:2 + ports: + - "7512:7512" + cap_add: + - SYS_PTRACE + depends_on: + - redis + - elasticsearch + environment: + - kuzzle_services__storageEngine__client__node=http://elasticsearch:9200 + - kuzzle_services__internalCache__node__host=redis + - kuzzle_services__memoryStorage__node__host=redis + - kuzzle_services__storageEngine__commonMapping__dynamic=true + - NODE_ENV=production + + redis: + image: redis:5 + + elasticsearch: + image: kuzzleio/elasticsearch:7 + ulimits: + nofile: 65536 + + doc-tests: + image: kuzzleio/snippets-tests + privileged: true + ports: + - '9229:9229' + depends_on: + - kuzzle + - doc-runner-java + volumes: + - ../..:/mnt + - /var/run/docker.sock:/var/run/docker.sock + - snippets:/var/snippets + environment: + - CONFIG_FILE=/mnt/.ci/doc/config.yml + + doc-runner-java: + image: adoptopenjdk/openjdk8 + command: > + bash -c ' + mkdir -p /var/snippets/java; + touch /tmp/runner_is_ready; + tail -f /dev/null + ' + volumes: + - ../..:/mnt + - snippets:/var/snippets + +volumes: + snippets: diff --git a/.ci/doc/java-project/build.gradle b/.ci/doc/java-project/build.gradle new file mode 100644 index 00000000..705342ac --- /dev/null +++ b/.ci/doc/java-project/build.gradle @@ -0,0 +1,30 @@ +plugins { + id 'java' +} + +group 'test.example.java' +version '1' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.google.code.gson:gson:2.8.5' +} + +jar { + manifest { + attributes( + 'Class-Path': configurations.compile.collect { it.getName() }.join(' '), + 'Main-Class': 'SnippetTest' + ) + } + from { + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + } +} \ No newline at end of file diff --git a/.ci/doc/java-project/gradle/wrapper/gradle-wrapper.jar b/.ci/doc/java-project/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..f3d88b1c Binary files /dev/null and b/.ci/doc/java-project/gradle/wrapper/gradle-wrapper.jar differ diff --git a/.ci/doc/java-project/gradle/wrapper/gradle-wrapper.properties b/.ci/doc/java-project/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..718c0f3d --- /dev/null +++ b/.ci/doc/java-project/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jan 17 11:19:10 CET 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-all.zip diff --git a/.ci/doc/java-project/gradlew b/.ci/doc/java-project/gradlew new file mode 100755 index 00000000..2fe81a7d --- /dev/null +++ b/.ci/doc/java-project/gradlew @@ -0,0 +1,183 @@ +#!/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/.ci/doc/java-project/gradlew.bat b/.ci/doc/java-project/gradlew.bat new file mode 100644 index 00000000..24467a14 --- /dev/null +++ b/.ci/doc/java-project/gradlew.bat @@ -0,0 +1,100 @@ +@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 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 init + +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 init + +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 + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +: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 %CMD_LINE_ARGS% + +: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/.ci/doc/java-project/libs/.keep b/.ci/doc/java-project/libs/.keep new file mode 100644 index 00000000..e69de29b diff --git a/.ci/doc/java-project/settings.gradle b/.ci/doc/java-project/settings.gradle new file mode 100644 index 00000000..682509ee --- /dev/null +++ b/.ci/doc/java-project/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'project' diff --git a/.ci/doc/java-project/src/main/java/.keep b/.ci/doc/java-project/src/main/java/.keep new file mode 100644 index 00000000..e69de29b diff --git a/.ci/doc/kotlin-project/build.gradle b/.ci/doc/kotlin-project/build.gradle new file mode 100644 index 00000000..dbad6232 --- /dev/null +++ b/.ci/doc/kotlin-project/build.gradle @@ -0,0 +1,30 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.3.72' +} + +group 'test.example.java' +version '1' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.google.code.gson:gson:2.8.5' +} + +jar { + manifest { + attributes( + 'Class-Path': configurations.compile.collect { it.getName() }.join(' '), + 'Main-Class': 'SnippetTestKt' + ) + } + from { + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + } +} \ No newline at end of file diff --git a/.ci/doc/kotlin-project/gradle/wrapper/gradle-wrapper.jar b/.ci/doc/kotlin-project/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..f3d88b1c Binary files /dev/null and b/.ci/doc/kotlin-project/gradle/wrapper/gradle-wrapper.jar differ diff --git a/.ci/doc/kotlin-project/gradle/wrapper/gradle-wrapper.properties b/.ci/doc/kotlin-project/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..718c0f3d --- /dev/null +++ b/.ci/doc/kotlin-project/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jan 17 11:19:10 CET 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-all.zip diff --git a/.ci/doc/kotlin-project/gradlew b/.ci/doc/kotlin-project/gradlew new file mode 100755 index 00000000..2fe81a7d --- /dev/null +++ b/.ci/doc/kotlin-project/gradlew @@ -0,0 +1,183 @@ +#!/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/.ci/doc/kotlin-project/gradlew.bat b/.ci/doc/kotlin-project/gradlew.bat new file mode 100644 index 00000000..24467a14 --- /dev/null +++ b/.ci/doc/kotlin-project/gradlew.bat @@ -0,0 +1,100 @@ +@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 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 init + +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 init + +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 + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +: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 %CMD_LINE_ARGS% + +: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/.ci/doc/kotlin-project/libs/.keep b/.ci/doc/kotlin-project/libs/.keep new file mode 100644 index 00000000..e69de29b diff --git a/.ci/doc/kotlin-project/settings.gradle b/.ci/doc/kotlin-project/settings.gradle new file mode 100644 index 00000000..682509ee --- /dev/null +++ b/.ci/doc/kotlin-project/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'project' diff --git a/.ci/doc/kotlin-project/src/main/java/.keep b/.ci/doc/kotlin-project/src/main/java/.keep new file mode 100644 index 00000000..e69de29b diff --git a/.ci/doc/templates/catch.tpl.java b/.ci/doc/templates/catch.tpl.java new file mode 100644 index 00000000..bd56af5f --- /dev/null +++ b/.ci/doc/templates/catch.tpl.java @@ -0,0 +1,25 @@ +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.Protocol.WebSocket; +import io.kuzzle.sdk.Options.Protocol.WebSocketOptions; +import io.kuzzle.sdk.Options.KuzzleOptions; +import java.util.concurrent.ConcurrentHashMap; +import io.kuzzle.sdk.CoreClasses.Responses.Response; + +public class SnippetTest { + private static Kuzzle kuzzle; + + public static void main(String[] argv) { + try { + kuzzle = new Kuzzle(new WebSocket("kuzzle")); + kuzzle.connect(); + [snippet-code] + System.out.println("Error"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } finally { + if (kuzzle != null) { + kuzzle.disconnect(); + } + } + } +} \ No newline at end of file diff --git a/.ci/doc/templates/default.tpl.java b/.ci/doc/templates/default.tpl.java new file mode 100644 index 00000000..114144b1 --- /dev/null +++ b/.ci/doc/templates/default.tpl.java @@ -0,0 +1,24 @@ +import io.kuzzle.sdk.Kuzzle; +import java.util.ArrayList; +import io.kuzzle.sdk.protocol.WebSocket; +import java.util.concurrent.ConcurrentHashMap; +import io.kuzzle.sdk.coreClasses.responses.Response; + +public class SnippetTest { + private static Kuzzle kuzzle; + + public static void main(String[] argv) { + try { + kuzzle = new Kuzzle(new WebSocket("kuzzle")); + kuzzle.connect(); + [snippet-code] + System.out.println("Success"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (kuzzle != null) { + kuzzle.disconnect(); + } + } + } +} \ No newline at end of file diff --git a/.ci/doc/templates/default.tpl.kt b/.ci/doc/templates/default.tpl.kt new file mode 100644 index 00000000..9ac4e380 --- /dev/null +++ b/.ci/doc/templates/default.tpl.kt @@ -0,0 +1,20 @@ +import io.kuzzle.sdk.Kuzzle +import io.kuzzle.sdk.protocol.WebSocket +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ExecutionException +import io.kuzzle.sdk.coreClasses.responses.Response + +fun main() { + val ws = WebSocket("kuzzle") + val kuzzle = Kuzzle(ws).apply { + connect() + } + try { + [snippet-code] + println("Success") + } catch (e: Exception) { + e.printStackTrace() + } finally { + kuzzle.disconnect() + } +} diff --git a/.ci/doc/templates/empty.tpl.java b/.ci/doc/templates/empty.tpl.java new file mode 100644 index 00000000..f6c250ed --- /dev/null +++ b/.ci/doc/templates/empty.tpl.java @@ -0,0 +1 @@ +[snippet-code] \ No newline at end of file diff --git a/.ci/doc/templates/print-result-array.tpl.java b/.ci/doc/templates/print-result-array.tpl.java new file mode 100644 index 00000000..c4fd68cd --- /dev/null +++ b/.ci/doc/templates/print-result-array.tpl.java @@ -0,0 +1,30 @@ +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.Protocol.WebSocket; +import io.kuzzle.sdk.Options.Protocol.WebSocketOptions; +import io.kuzzle.sdk.Options.KuzzleOptions; +import io.kuzzle.sdk.Options.SubscribeOptions; +import io.kuzzle.sdk.CoreClasses.Responses.Response; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.ArrayList; + +public class SnippetTest { + private static Kuzzle kuzzle; + + public static void main(String[] argv) { + try { + kuzzle = new Kuzzle(new WebSocket("kuzzle")); + kuzzle.connect(); + [snippet-code] + for (Object o : result.get("successes")) { + System.out.println(o); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (kuzzle != null) { + kuzzle.disconnect(); + } + } + } +} \ No newline at end of file diff --git a/.ci/doc/templates/print-result-arraylist.tpl.java b/.ci/doc/templates/print-result-arraylist.tpl.java new file mode 100644 index 00000000..ca5a96dc --- /dev/null +++ b/.ci/doc/templates/print-result-arraylist.tpl.java @@ -0,0 +1,30 @@ +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.Protocol.WebSocket; +import io.kuzzle.sdk.Options.Protocol.WebSocketOptions; +import io.kuzzle.sdk.Options.KuzzleOptions; +import io.kuzzle.sdk.Options.SubscribeOptions; +import io.kuzzle.sdk.CoreClasses.Responses.Response; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.ArrayList; + +public class SnippetTest { + private static Kuzzle kuzzle; + + public static void main(String[] argv) { + try { + kuzzle = new Kuzzle(new WebSocket("kuzzle")); + kuzzle.connect(); + [snippet-code] + for (Object o : result) { + System.out.println(o); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (kuzzle != null) { + kuzzle.disconnect(); + } + } + } +} \ No newline at end of file diff --git a/.ci/doc/templates/print-result.tpl.java b/.ci/doc/templates/print-result.tpl.java new file mode 100644 index 00000000..02f303e0 --- /dev/null +++ b/.ci/doc/templates/print-result.tpl.java @@ -0,0 +1,25 @@ +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.protocol.WebSocket; +import io.kuzzle.sdk.coreClasses.responses.Response; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.ArrayList; + +public class SnippetTest { + private static Kuzzle kuzzle; + + public static void main(String[] argv) { + try { + kuzzle = new Kuzzle(new WebSocket("kuzzle")); + kuzzle.connect(); + [snippet-code] + System.out.println(result.toString()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (kuzzle != null) { + kuzzle.disconnect(); + } + } + } +} \ No newline at end of file diff --git a/.ci/doc/templates/print-result.tpl.kt b/.ci/doc/templates/print-result.tpl.kt new file mode 100644 index 00000000..b9510f13 --- /dev/null +++ b/.ci/doc/templates/print-result.tpl.kt @@ -0,0 +1,20 @@ +import io.kuzzle.sdk.Kuzzle +import io.kuzzle.sdk.protocol.WebSocket +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ExecutionException +import io.kuzzle.sdk.coreClasses.responses.Response + +fun main() { + val ws = WebSocket("kuzzle") + val kuzzle = Kuzzle(ws).apply { + connect() + } + try { + [snippet-code] + println(result.toString()) + } catch (e: Exception) { + e.printStackTrace() + } finally { + kuzzle.disconnect() + } +} diff --git a/.ci/doc/templates/without-connect.tpl.java b/.ci/doc/templates/without-connect.tpl.java new file mode 100644 index 00000000..c01bc7ce --- /dev/null +++ b/.ci/doc/templates/without-connect.tpl.java @@ -0,0 +1,20 @@ +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.protocol.WebSocket; + +public class SnippetTest { + private static Kuzzle kuzzle; + + public static void main(String[] argv) { + try { + kuzzle = new Kuzzle(new WebSocket("kuzzle")); + [snippet-code] + System.out.println("Success"); + } catch (Exception e) { + System.err.println(e.getMessage()); + } finally { + if (kuzzle != null) { + kuzzle.disconnect(); + } + } + } +} diff --git a/.ci/doc/templates/without-connect.tpl.kt b/.ci/doc/templates/without-connect.tpl.kt new file mode 100644 index 00000000..a9f78f53 --- /dev/null +++ b/.ci/doc/templates/without-connect.tpl.kt @@ -0,0 +1,17 @@ +import io.kuzzle.sdk.Kuzzle +import io.kuzzle.sdk.protocol.WebSocket +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ExecutionException + +fun main() { + val ws = WebSocket("kuzzle") + val kuzzle = Kuzzle(ws) + try { + [snippet-code] + println("Success") + } catch (e: Exception) { + e.printStackTrace() + } finally { + kuzzle.disconnect() + } +} \ No newline at end of file diff --git a/.ci/doc/templates/without-ctor.tpl.java b/.ci/doc/templates/without-ctor.tpl.java new file mode 100644 index 00000000..fd35ba7e --- /dev/null +++ b/.ci/doc/templates/without-ctor.tpl.java @@ -0,0 +1,13 @@ +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.protocol.WebSocket; + +public class SnippetTest { + public static void main(String[] argv) { + try { + [snippet-code] + System.out.println("Success"); + } catch (Exception e) { + System.err.println((e.getMessage())); + } + } +} \ No newline at end of file diff --git a/.ci/doc/templates/without-ctor.tpl.kt b/.ci/doc/templates/without-ctor.tpl.kt new file mode 100644 index 00000000..84841516 --- /dev/null +++ b/.ci/doc/templates/without-ctor.tpl.kt @@ -0,0 +1,13 @@ +import io.kuzzle.sdk.Kuzzle +import io.kuzzle.sdk.protocol.WebSocket +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ExecutionException + +fun main() { + try { + [snippet-code] + println("Success") + } catch (e: Exception) { + e.printStackTrace() + } +} diff --git a/.ci/doc/test-snippet.sh b/.ci/doc/test-snippet.sh new file mode 100755 index 00000000..90fa1d74 --- /dev/null +++ b/.ci/doc/test-snippet.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +if [ ${1: -3} == ".kt" ] +then + cp /mnt/build/libs/sdk-jvm-[0-9+].[0-9+].[0-9+].jar /mnt/.ci/doc/kotlin-project/libs/ && cp $1 /mnt/.ci/doc/kotlin-project/src/main/java/SnippetTest.kt && cd /mnt/.ci/doc/kotlin-project/ && ./gradlew build && java -classpath 'libs/sdk-jvm-1.0.0.jar:' -jar build/libs/project-1.jar +else + cp /mnt/build/libs/sdk-jvm-[0-9+].[0-9+].[0-9+].jar /mnt/.ci/doc/java-project/libs/ && cp $1 /mnt/.ci/doc/java-project/src/main/java/SnippetTest.java && cd /mnt/.ci/doc/java-project/ && ./gradlew build && java -classpath 'libs/sdk-jvm-1.0.0.jar:' -jar build/libs/project-1.jar +fi diff --git a/.gitignore b/.gitignore index 7bccfb11..98fea147 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,15 @@ -build/ -.gradle/ -out/ -.idea/ -src/main/kotlin/Main.kt \ No newline at end of file +.gradle +build +out +.idea +bin +*.iml +*.class +bin +.classpath +.project + +doc/framework +node_modules + +src/main/kotlin/Main.kt diff --git a/.travis.yml b/.travis.yml index 466d1bf2..532e9a85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ job: include: - - stage: Unit tests + - stage: Tests name: Unit tests SDK Kotlin language: kotlin jdk: openjdk8 @@ -17,8 +17,104 @@ job: script: - ./gradlew test + - stage: Tests + name: Dead link check + if: + type = pull_request OR type = push AND branch =~ /^master|[0-9]+-(dev|stable)$/ + OR type = cron + language: node_js + node_js: 12 + before_script: + - npm ci + - npm run doc-prepare + - $(npm bin)/kuzdoc iterate-repos:install --repos_path doc/framework/.repos/ + - $(npm bin)/kuzdoc framework:link -d /sdk/java/3/ -v 3 + + script: + - gem install typhoeus + - cd doc/framework/ && HYDRA_MAX_CONCURRENCY=20 ruby .ci/dead-links.rb -p src/sdk/java/3/ + + - stage: Tests + name: Documentation Snippets + if: type = pull_request OR type = push AND branch =~ /^master|[0-9]+-dev$/ OR type = cron + language: node_js + node_js: 12 + script: docker-compose -f .ci/doc/docker-compose.yml run doc-tests index + + - stage: Deployments + name: Deploy documentation to next-docs.kuzzle.io + if: type = push AND branch =~ /^[0-9]+-dev$/ + language: node_js + node_js: 12 + env: + - BRANCH=dev + - NODE_ENV=production + - S3_BUCKET=docs-next.kuzzle.io + - CLOUDFRONT_DISTRIBUTION_ID=E2ZCCEK9GRB49U + - AWS_DEFAULT_REGION=us-west-2 + + addons: + apt: + update: true + packages: + - python + - python-pip + + install: + - pip install awscli --upgrade --user + - npm ci + + script: + - npm run doc-prepare + - npm run doc-build + + deploy: + provider: script + script: + - npm run doc-upload + skip_cleanup: true + on: + all_branches: true + + after_deploy: + - npm run doc-cloudfront + + + - stage: Deployments + name: Deploy documentation to docs.kuzzle.io + if: type = push AND branch =~ /^master|[0-9]+-stable$/ + language: node_js + node_js: 12 + env: + - NODE_ENV=production + - S3_BUCKET=docs.kuzzle.io + - CLOUDFRONT_DISTRIBUTION_ID=E3D6RP0POLCJMM + - AWS_DEFAULT_REGION=us-west-2 + addons: + apt: + packages: + - python + - python-pip + install: + - pip install awscli --upgrade --user + - npm ci + script: + - npm run doc-prepare + - npm run doc-build + deploy: + provider: script + script: + - npm run doc-upload + skip_cleanup: true + on: + all_branches: true + after_deploy: + - npm run doc-cloudfront + stages: - - name: Unit Tests + - name: Tests if: type =~ /(cron|push|pull_request)/ AND branch =~ /^master|[0-9]+-(dev|stable)$/ - name: Builds - if: type =~ /(cron|push|pull_request)/ AND branch =~ /^master|[0-9]+-(dev|stable)$/ \ No newline at end of file + if: type =~ /(cron|push|pull_request)/ AND branch =~ /^master|[0-9]+-(dev|stable)$/ + - name: Deployments + if: type =~ /(cron|push|pull_request)/ AND branch =~ /^master|[0-9]+-stable$/ \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 7c3d06d8..8acf2297 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,9 +8,9 @@ plugins { } group = "io.kuzzle.sdk" -version = "0.0.1" +version = "1.0.0" -val ktorVersion = "1.3.1" +val ktorVersion = "1.3.2" repositories { jcenter() @@ -33,6 +33,7 @@ dependencies { testImplementation("io.ktor:ktor-client-json-jvm:$ktorVersion") testImplementation("io.ktor:ktor-client-mock-js:$ktorVersion") testImplementation("io.ktor:ktor-client-mock-native:$ktorVersion") + } // Configure existing Dokka task to output HTML to typical Javadoc directory diff --git a/doc/1/.vuepress b/doc/1/.vuepress new file mode 120000 index 00000000..4ea2349b --- /dev/null +++ b/doc/1/.vuepress @@ -0,0 +1 @@ +../framework/src/.vuepress/ \ No newline at end of file diff --git a/doc/1/controllers/realtime/count/index.md b/doc/1/controllers/realtime/count/index.md new file mode 100644 index 00000000..1c8cbab5 --- /dev/null +++ b/doc/1/controllers/realtime/count/index.md @@ -0,0 +1,56 @@ +--- +code: true +type: page +title: count +description: Returns the number of other connections sharing the same subscription. +--- + +# count + +Returns the number of other connections sharing the same subscription. + +:::: tabs +::: tab Java + +## Arguments + +```java +public CompletableFuture count(String roomId) + throws NotConnectedException, InternalException +``` + +| Argument | Type | Description | +|-----------|-------------------|----------------------| +| `roomId` |
String
| Subscription room ID | + +## Return + +Returns the number of active connections using the same provided subscription room. + +## Usage + +<<< ./snippets/count-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun count(roomId: String): CompletableFuture +``` + +| Argument | Type | Description | +|-----------|-------------------|----------------------| +| `roomId` |
String
| Subscription room ID | + +## Return + +Returns the number of active connections using the same provided subscription room. + +## Usage + +<<< ./snippets/count-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/controllers/realtime/count/snippets/count-java.java b/doc/1/controllers/realtime/count/snippets/count-java.java new file mode 100644 index 00000000..39072b5a --- /dev/null +++ b/doc/1/controllers/realtime/count/snippets/count-java.java @@ -0,0 +1,16 @@ +ConcurrentHashMap filters = new ConcurrentHashMap<>(); +filters.put("exists", "name"); + +final String roomId = kuzzle.getRealtimeController().subscribe( + "nyc-open-data", + "yellow-taxi", + filters, + notification -> { + if (notification.getScope().equals("in")) { + System.out.println("Document entered the scope"); + } else { + System.out.println("Document left the scope"); + } +}).get(); + +final Integer result = kuzzle.getRealtimeController().count(roomId).get(); \ No newline at end of file diff --git a/doc/1/controllers/realtime/count/snippets/count-java.test.yml b/doc/1/controllers/realtime/count/snippets/count-java.test.yml new file mode 100644 index 00000000..0447c2d0 --- /dev/null +++ b/doc/1/controllers/realtime/count/snippets/count-java.test.yml @@ -0,0 +1,7 @@ +name: java-Realtime#count +description: Counts subscribers for a subscription room. +hooks: + before: + after: +template: print-result +expected: 1 \ No newline at end of file diff --git a/doc/1/controllers/realtime/count/snippets/count-kotlin.kt b/doc/1/controllers/realtime/count/snippets/count-kotlin.kt new file mode 100644 index 00000000..69452580 --- /dev/null +++ b/doc/1/controllers/realtime/count/snippets/count-kotlin.kt @@ -0,0 +1,16 @@ +val filters: ConcurrentHashMap = ConcurrentHashMap().apply { + put("exists", "name") +} + +val roomId: String = kuzzle.realtimeController.subscribe( + "nyc-open-data", + "yellow-taxi", + filters) { + if (it.scope == "in") { + println("Document entered the scope") + } else { + println("Document left the scope") + } + }.get() + +val result: Int = kuzzle.realtimeController.count(roomId).get() \ No newline at end of file diff --git a/doc/1/controllers/realtime/count/snippets/count-kotlin.test.yml b/doc/1/controllers/realtime/count/snippets/count-kotlin.test.yml new file mode 100644 index 00000000..3394e7cb --- /dev/null +++ b/doc/1/controllers/realtime/count/snippets/count-kotlin.test.yml @@ -0,0 +1,7 @@ +name: kotlin-Realtime#count +description: Counts subscribers for a subscription room. +hooks: + before: + after: +template: print-result +expected: 1 \ No newline at end of file diff --git a/doc/1/controllers/realtime/index.md b/doc/1/controllers/realtime/index.md new file mode 100644 index 00000000..0609f3b0 --- /dev/null +++ b/doc/1/controllers/realtime/index.md @@ -0,0 +1,8 @@ +--- +code: true +type: branch +title: Realtime +description: Realtime Controller +--- + +# Realtime Controller diff --git a/doc/1/controllers/realtime/publish/index.md b/doc/1/controllers/realtime/publish/index.md new file mode 100644 index 00000000..a1f2035c --- /dev/null +++ b/doc/1/controllers/realtime/publish/index.md @@ -0,0 +1,59 @@ +--- +code: true +type: page +title: publish +description: Publishes a real-time message. +--- + +# publish + +Sends a real-time message to Kuzzle. The message will be broadcasted to all clients with subscriptions matching the index, the collection and the message content. + +The index and collection are indicative and serve only to distinguish the rooms. They are not required to exist in the database. + +**Note:** real-time messages are not persisted in the database. + +:::: tabs +::: tab Java + +## Arguments + +```java +public CompletableFuture publish( + String index, + String collection, + ConcurrentHashMap message) + throws NotConnectedException, InternalException +``` + +| Argument | Type | Description | +|--------------|--------------------|-------------------------------------| +| `index` |
String
| Index name | +| `collection` |
String
| Collection name | +| `message` |
ConcurrentHashMap
| ConcurrentHashMap representing a JSON payload | + +## Usage + +<<< ./snippets/publish-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun publish(index: String, collection: String, message: ConcurrentHashMap): CompletableFuture +``` + +| Argument | Type | Description | +|--------------|--------------------|-------------------------------------| +| `index` |
String
| Index name | +| `collection` |
String
| Collection name | +| `message` |
ConcurrentHashMap
| ConcurrentHashMap representing a JSON payload | + +## Usage + +<<< ./snippets/publish-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/controllers/realtime/publish/snippets/publish-java.java b/doc/1/controllers/realtime/publish/snippets/publish-java.java new file mode 100644 index 00000000..db209db1 --- /dev/null +++ b/doc/1/controllers/realtime/publish/snippets/publish-java.java @@ -0,0 +1,4 @@ +ConcurrentHashMap document = new ConcurrentHashMap<>(); +document.put("name", "nina-vkote"); + +kuzzle.getRealtimeController().publish("my-index", "my-collection", document); \ No newline at end of file diff --git a/doc/1/controllers/realtime/publish/snippets/publish-java.test.yml b/doc/1/controllers/realtime/publish/snippets/publish-java.test.yml new file mode 100644 index 00000000..91e31b5e --- /dev/null +++ b/doc/1/controllers/realtime/publish/snippets/publish-java.test.yml @@ -0,0 +1,7 @@ +name: java-Realtime#publish +description: Publishes a realtime message. +hooks: + before: + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/controllers/realtime/publish/snippets/publish-kotlin.kt b/doc/1/controllers/realtime/publish/snippets/publish-kotlin.kt new file mode 100644 index 00000000..4413f294 --- /dev/null +++ b/doc/1/controllers/realtime/publish/snippets/publish-kotlin.kt @@ -0,0 +1,5 @@ +val document: ConcurrentHashMap = ConcurrentHashMap().apply { + put("name", "nina-vkote") +} + +kuzzle.realtimeController.publish("my-index", "my-collection", document) \ No newline at end of file diff --git a/doc/1/controllers/realtime/publish/snippets/publish-kotlin.test.yml b/doc/1/controllers/realtime/publish/snippets/publish-kotlin.test.yml new file mode 100644 index 00000000..d2fb9fe1 --- /dev/null +++ b/doc/1/controllers/realtime/publish/snippets/publish-kotlin.test.yml @@ -0,0 +1,7 @@ +name: kotlin-Realtime#publish +description: Publishes a realtime message. +hooks: + before: + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/index.md b/doc/1/controllers/realtime/subscribe/index.md new file mode 100644 index 00000000..7307a75a --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/index.md @@ -0,0 +1,142 @@ +--- +code: true +type: page +title: subscribe +description: Subscribes to real-time notifications. +--- + +# Subscribe + +Subscribes by providing a set of filters: messages, document changes and, optionally, user events matching the provided filters will generate [real-time notifications](/core/2/api/essentials/notifications), sent to you in real-time by Kuzzle. + +:::: tabs +::: tab Java + +## Arguments + +```java +public CompletableFuture subscribe( + String index, + String collection, + ConcurrentHashMap filters, + String scope, + String users, + boolean subscribeToSelf, + ConcurrentHashMap volatiles, + NotificationHandler handler, +) throws NotConnectedException, InternalException + +public CompletableFuture subscribe( + String index, + String collection, + ConcurrentHashMap filters, + String scope, + String users, + boolean subscribeToSelf, + NotificationHandler handler, +) throws NotConnectedException, InternalException + +public CompletableFuture subscribe( + String index, + String collection, + ConcurrentHashMap filters, + String scope, + String users, + NotificationHandler handler, +) throws NotConnectedException, InternalException + +public CompletableFuture subscribe( + String index, + String collection, + ConcurrentHashMap filters, + String scope, + NotificationHandler handler, +) throws NotConnectedException, InternalException + +public CompletableFuture subscribe( + String index, + String collection, + ConcurrentHashMap filters, + NotificationHandler handler, +) throws NotConnectedException, InternalException +``` + +| Argument | Type | Description | +|--------------|-----------------------------------------|----------------------------------------------------------------------------------------------------------------| +| `index` |
String/pre>                       | Index name                                                                                                     |
+| `collection` | 
String
| Collection name | +| `filters` |
ConcurrentHashMap
| ConcurrentHashMap representing a set of filters following [Koncorde syntax](/core/2/guides/cookbooks/realtime-api/terms) | +| `handler` |
NotificationHandler
| Handler function to handle notifications | +| `scope` |
String

(`all`) | Subscribes to document entering or leaving the scope
Possible values: all, in, out, none | +| `users` |
String

(`none`) | Subscribes to users entering or leaving the room
Possible values: all, in, out, none | +| `subscribeToSelf` |
boolean

(`true`) | Subscribes to notifications fired by our own queries | +| `volatile` |
ConcurrentHashMap

(`{}}`) | ConcurrentHashMap representing subscription information, used in user join/leave notifications | + +### handler + +Handler function that will be called each time a new notification is received. +The handler will receive a [Response](/sdk/jvm/1/core-classes/response) as its only argument. + +## Return + +The room ID. + +## Usage + +Simple subscription to document notifications_ + +<<< ./snippets/document-notifications-java.java + +Subscription to document notifications with scope option_ + +<<< ./snippets/document-notifications-leave-scope-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun subscribe( + index: String?, + collection: String?, + filters: ConcurrentHashMap, + scope: String = "all", + users: String = "all", + subscribeToSelf: Boolean = true, + volatiles: ConcurrentHashMap = ConcurrentHashMap(), + handler: (Response) -> Unit): CompletableFuture +``` + +| Argument | Type | Description | +|--------------|-----------------------------------------|----------------------------------------------------------------------------------------------------------------| +| `index` |
String/pre>                       | Index name                                                                                                     |
+| `collection` | 
String
| Collection name | +| `filters` |
ConcurrentHashMap
| ConcurrentHashMap representing a set of filters following [Koncorde syntax](/core/2/guides/cookbooks/realtime-api/terms) | +| `handler` |
NotificationHandler
| Handler function to handle notifications | +| `scope` |
String

(`all`) | Subscribes to document entering or leaving the scope
Possible values: all, in, out, none | +| `users` |
String

(`none`) | Subscribes to users entering or leaving the room
Possible values: all, in, out, none | +| `subscribeToSelf` |
boolean

(`true`) | Subscribes to notifications fired by our own queries | +| `volatile` |
ConcurrentHashMap

(`{}`) | ConcurrentHashMap representing subscription information, used in user join/leave notifications | + +### handler + +Handler function that will be called each time a new notification is received. +The handler will receive a [Response](/sdk/jvm/1/core-classes/response) as its only argument. + +## Return + +The room ID. + +## Usage + +Simple subscription to document notifications_ + +<<< ./snippets/document-notifications-kotlin.kt + +Subscription to document notifications with scope option_ + +<<< ./snippets/document-notifications-leave-scope-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-java.java b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-java.java new file mode 100644 index 00000000..a3c7400a --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-java.java @@ -0,0 +1,26 @@ +ConcurrentHashMap filters = new ConcurrentHashMap<>(); +filters.put("exists", "name"); + +ConcurrentHashMap document = new ConcurrentHashMap<>(); +document.put("name", "nina-vkote"); + +final String roomId = kuzzle.getRealtimeController().subscribe( + "nyc-open-data", + "yellow-taxi", + filters, + notification -> { + if (notification.getScope().equals("in")) { + System.out.println("Document entered the scope"); + } else { + System.out.println("Document left the scope"); + } +}).get(); + +ConcurrentHashMap query = new ConcurrentHashMap<>(); +query.put("controller", "document"); +query.put("action", "create"); +query.put("index", "nyc-open-data"); +query.put("collection", "yellow-taxi"); +query.put("_id", "nina-vkote"); +query.put("body", document); +kuzzle.query(query).get(); \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-java.test.yml b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-java.test.yml new file mode 100644 index 00000000..cdb58825 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-java.test.yml @@ -0,0 +1,10 @@ +name: java-Realtime#Subscribe-documents +description: Subscribes to document notifications. +hooks: + before: | + curl -X POST kuzzle:7512/nyc-open-data/_create + curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi/ + curl -X DELETE kuzzle:7512/nyc-open-data/yellow-taxi/nina-vkote + after: +template: default +expected: Document entered the scope \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-kotlin.kt b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-kotlin.kt new file mode 100644 index 00000000..69fe4427 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-kotlin.kt @@ -0,0 +1,28 @@ +val filters: ConcurrentHashMap = ConcurrentHashMap().apply { + put("exists", "name") +} + +val roomId: String = kuzzle.realtimeController.subscribe( + "nyc-open-data", + "yellow-taxi", + filters) { + if (it.scope == "in") { + println("Document entered the scope") + } else { + println("Document left the scope") + } + }.get() + +val document: ConcurrentHashMap = ConcurrentHashMap().apply { + put("name", "nina-vkote") +} +val query: ConcurrentHashMap = ConcurrentHashMap().apply { + put("controller", "document"); + put("action", "create"); + put("index", "nyc-open-data"); + put("collection", "yellow-taxi"); + put("_id", "nina-vkote"); + put("body", document); +} + +kuzzle.query(query).get() \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-kotlin.test.yml b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-kotlin.test.yml new file mode 100644 index 00000000..fa2d2f41 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-kotlin.test.yml @@ -0,0 +1,10 @@ +name: kotlin-Realtime#Subscribe-documents +description: Subscribes to document notifications. +hooks: + before: | + curl -X POST kuzzle:7512/nyc-open-data/_create + curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi/ + curl -X DELETE kuzzle:7512/nyc-open-data/yellow-taxi/nina-vkote + after: +template: default +expected: Document entered the scope \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-java.java b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-java.java new file mode 100644 index 00000000..f41dc4c5 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-java.java @@ -0,0 +1,36 @@ +ConcurrentHashMap filters = new ConcurrentHashMap<>(); +ConcurrentHashMap range = new ConcurrentHashMap<>(); +ConcurrentHashMap age = new ConcurrentHashMap<>(); + +age.put("lte", 20); +range.put("age", age); +filters.put("range", range); + +kuzzle.getRealtimeController().subscribe( + "nyc-open-data", + "yellow-taxi", + filters, + "all", + "all", + notification -> { + if (notification.getScope().equals("out")) { + System.out.println("Document left the scope"); + } else { + System.out.println("Document moved in the scope"); + } + }).get(); + +ConcurrentHashMap document = new ConcurrentHashMap<>(); +document.put("age", 19); +ConcurrentHashMap query = new ConcurrentHashMap<>(); +query.put("controller", "document"); +query.put("action", "create"); +query.put("index", "nyc-open-data"); +query.put("collection", "yellow-taxi"); +query.put("_id", "nina-vkote"); +query.put("body", document); +kuzzle.query(query).get(); + +query.put("action", "update"); +document.put("age", 42); +kuzzle.query(query).get(); \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-java.test.yml b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-java.test.yml new file mode 100644 index 00000000..68d96164 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-java.test.yml @@ -0,0 +1,10 @@ +name: java-Realtime#Subscribe-documents-leave-scope +description: Subscribes to documents leaving the scope. +hooks: + before: | + curl -X POST kuzzle:7512/nyc-open-data/_create + curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi/ + curl -X DELETE kuzzle:7512/nyc-open-data/yellow-taxi/nina-vkote + after: +template: default +expected: Document\ moved\ in\ the\ scope \ No newline at end of file diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-kotlin.kt b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-kotlin.kt new file mode 100644 index 00000000..b4ef93a3 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-kotlin.kt @@ -0,0 +1,36 @@ +val filters: ConcurrentHashMap = ConcurrentHashMap().apply { + put("range", ConcurrentHashMap().apply { + put("age", ConcurrentHashMap().apply { + put("lte", 20) + }) + }) +} + +val roomId: String = kuzzle.realtimeController.subscribe( + "nyc-open-data", + "yellow-taxi", + filters) { + if (it.scope == "in") { + println("Document entered the scope") + } else { + println("Document moved in the scope") + } +}.get() + +val document: ConcurrentHashMap = ConcurrentHashMap().apply { + put("age", 19) +} +val query: ConcurrentHashMap = ConcurrentHashMap().apply { + put("controller", "document"); + put("action", "create"); + put("index", "nyc-open-data"); + put("collection", "yellow-taxi"); + put("_id", "nina-vkote"); + put("body", document); +} + +kuzzle.query(query).get() + +query.put("action", "update") +document.put("age", 42) +kuzzle.query(query).get() diff --git a/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-kotlin.test.yml b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-kotlin.test.yml new file mode 100644 index 00000000..ad227e27 --- /dev/null +++ b/doc/1/controllers/realtime/subscribe/snippets/document-notifications-leave-scope-kotlin.test.yml @@ -0,0 +1,10 @@ +name: kotlin-Realtime#Subscribe-documents-leave-scope +description: Subscribes to documents leaving the scope. +hooks: + before: | + curl -X POST kuzzle:7512/nyc-open-data/_create + curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi/ + curl -X DELETE kuzzle:7512/nyc-open-data/yellow-taxi/nina-vkote + after: +template: default +expected: Document\ moved\ in\ the\ scope \ No newline at end of file diff --git a/doc/1/controllers/realtime/unsubscribe/index.md b/doc/1/controllers/realtime/unsubscribe/index.md new file mode 100644 index 00000000..5c136be1 --- /dev/null +++ b/doc/1/controllers/realtime/unsubscribe/index.md @@ -0,0 +1,48 @@ +--- +code: true +type: page +title: unsubscribe +description: Removes a subscription. +--- + +# unsubscribe + +Removes a subscription. + +:::: tabs +::: tab Java + +## Arguments + +```java +public CompletableFuture unsubscribe(final String roomId) + throws NotConnectedException, InternalException +``` + +| Argument | Type | Description | +|-----------|--------------------|----------------------| +| `roomId` |
String
| Subscription room ID | + +## Usage + +<<< ./snippets/unsubscribe-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun unsubscribe(roomId: String): CompletableFuture +``` + +| Argument | Type | Description | +|-----------|--------------------|----------------------| +| `roomId` |
String
| Subscription room ID | + +## Usage + +<<< ./snippets/unsubscribe-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-java.java b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-java.java new file mode 100644 index 00000000..bccc0814 --- /dev/null +++ b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-java.java @@ -0,0 +1,19 @@ +ConcurrentHashMap filters = new ConcurrentHashMap<>(); +filters.put("exists", "name"); + +ConcurrentHashMap document = new ConcurrentHashMap<>(); +document.put("name", "nina-vkote"); + +final String roomId = kuzzle.getRealtimeController().subscribe( + "nyc-open-data", + "yellow-taxi", + filters, + notification -> { + if (notification.getScope().equals("in")) { + System.out.println("Document entered the scope"); + } else { + System.out.println("Document left the scope"); + } +}).get(); + +kuzzle.getRealtimeController().unsubscribe(roomId).get(); \ No newline at end of file diff --git a/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-java.test.yml b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-java.test.yml new file mode 100644 index 00000000..26f7cec5 --- /dev/null +++ b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-java.test.yml @@ -0,0 +1,7 @@ +name: java-Realtime#unsubscribe +description: Removes a subscription. +hooks: + before: + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-kotlin.kt b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-kotlin.kt new file mode 100644 index 00000000..e0668665 --- /dev/null +++ b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-kotlin.kt @@ -0,0 +1,20 @@ +val filters: ConcurrentHashMap = ConcurrentHashMap().apply { + put("exists", "name") +} + +val roomId: String = kuzzle.realtimeController.subscribe( + "nyc-open-data", + "yellow-taxi", + filters) { + if (it.scope == "in") { + println("Document entered the scope") + } else { + println("Document left the scope") + } +}.get() + +val document: ConcurrentHashMap = ConcurrentHashMap().apply { + put("name", "nina-vkote") +} + +kuzzle.realtimeController.unsubscribe(roomId) \ No newline at end of file diff --git a/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-kotlin.test.yml b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-kotlin.test.yml new file mode 100644 index 00000000..41618386 --- /dev/null +++ b/doc/1/controllers/realtime/unsubscribe/snippets/unsubscribe-kotlin.test.yml @@ -0,0 +1,7 @@ +name: kotlin-Realtime#unsubscribe +description: Removes a subscription. +hooks: + before: + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/error-response/index.md b/doc/1/core-classes/error-response/index.md new file mode 100644 index 00000000..bae90d65 --- /dev/null +++ b/doc/1/core-classes/error-response/index.md @@ -0,0 +1,7 @@ +--- +code: true +type: branch +title: ErrorResponse +description: ErrorResponse object documentation +order: 0 +--- \ No newline at end of file diff --git a/doc/1/core-classes/error-response/introduction/index.md b/doc/1/core-classes/error-response/introduction/index.md new file mode 100644 index 00000000..bdac275d --- /dev/null +++ b/doc/1/core-classes/error-response/introduction/index.md @@ -0,0 +1,20 @@ +--- +code: false +type: page +title: Introduction +description: ErrorResponse object description +order: 0 +--- + +## ErrorResponse + +`ErrorResponse` is a **serializable** class representing a raw Kuzzle response with error. + +## Properties + +| Property | Type | Description | +|--- |--- |--- | +| `id` |
String
| Error ID | +| `message` |
String
| Error message | +| `stack` |
String
| Error stack | +| `status` |
int
| Response status, following HTTP status codes. | diff --git a/doc/1/core-classes/kuzzle/connect/index.md b/doc/1/core-classes/kuzzle/connect/index.md new file mode 100644 index 00000000..dc407c46 --- /dev/null +++ b/doc/1/core-classes/kuzzle/connect/index.md @@ -0,0 +1,37 @@ +--- +code: true +type: page +title: Connect +description: Connects the SDK to Kuzzle +--- + +# Connect + +Connects to Kuzzle using the underlying protocol `connect` method. + +Subsequent calls have no effect if the SDK is already connected. + +:::: tabs +::: tab Java +## Arguments + +```java +public void connect() throws Exception; +``` + +## Usage + +<<< ./snippets/connect-java.java +::: +::: tab Kotlin +## Arguments + +```kotlin +fun connect() +``` + +## Usage + +<<< ./snippets/connect-kotlin.kt +::: +:::: diff --git a/doc/1/core-classes/kuzzle/connect/snippets/connect-java.java b/doc/1/core-classes/kuzzle/connect/snippets/connect-java.java new file mode 100644 index 00000000..599a215c --- /dev/null +++ b/doc/1/core-classes/kuzzle/connect/snippets/connect-java.java @@ -0,0 +1 @@ +kuzzle.connect(); diff --git a/doc/1/core-classes/kuzzle/connect/snippets/connect-java.test.yml b/doc/1/core-classes/kuzzle/connect/snippets/connect-java.test.yml new file mode 100644 index 00000000..252e1bfe --- /dev/null +++ b/doc/1/core-classes/kuzzle/connect/snippets/connect-java.test.yml @@ -0,0 +1,8 @@ +--- +name: java-kuzzle#Connect +description: Connects the SDK to Kuzzle +hooks: + before: + after: +template: without-connect +expected: Success diff --git a/doc/1/core-classes/kuzzle/connect/snippets/connect-kotlin.kt b/doc/1/core-classes/kuzzle/connect/snippets/connect-kotlin.kt new file mode 100644 index 00000000..e601b958 --- /dev/null +++ b/doc/1/core-classes/kuzzle/connect/snippets/connect-kotlin.kt @@ -0,0 +1 @@ +kuzzle.connect() diff --git a/doc/1/core-classes/kuzzle/connect/snippets/connect-kotlin.test.yml b/doc/1/core-classes/kuzzle/connect/snippets/connect-kotlin.test.yml new file mode 100644 index 00000000..f0e981f5 --- /dev/null +++ b/doc/1/core-classes/kuzzle/connect/snippets/connect-kotlin.test.yml @@ -0,0 +1,8 @@ +--- +name: kotlin-kuzzle#Connect +description: Connects the SDK to Kuzzle +hooks: + before: + after: +template: without-connect +expected: Success diff --git a/doc/1/core-classes/kuzzle/constructor/index.md b/doc/1/core-classes/kuzzle/constructor/index.md new file mode 100644 index 00000000..22aedb01 --- /dev/null +++ b/doc/1/core-classes/kuzzle/constructor/index.md @@ -0,0 +1,87 @@ +--- +code: true +type: page +title: Constructor +description: Creates a new Kuzzle object connected to the backend +order: 100 +--- + +# Constructor + +Use this constructor to create a new instance of the SDK. +Each instance represents a different connection to a Kuzzle server with specific options. + +:::: tabs +::: tab Java +## Arguments + +```java +public Kuzzle( + AbstractProtocol networkProtocol, + bool subscribeToSelf +) throws IllegalArgumentException + +public Kuzzle( + AbstractProtocol networkProtocol +) throws IllegalArgumentException +``` + +
+ +| Argument | Type | Description | +| ---------- | ------------------- | --------------------------------- | +| `networkProtocol` |
AbstractProtocol
| Protocol used by the SDK instance | +| `autoResubscribe` |
boolean

(`true`) | Class which contains options | + +## networkProtocol + +The protocol used to connect to the Kuzzle instance. +It can be one of the following available protocols: + +- [WebSocket](/sdk/java/3/protocols/websocket) + +## Return + +The `Kuzzle` SDK instance. + +## Throws + +Can throw an [IllegalArgumentException](/sdk/java/3/exceptions/illegal-argument-exception) + +## Usage + +<<< ./snippets/constructor-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun Kuzzle(protocol: AbstractProtocol, autoResubscribe: Boolean = true) +``` + +
+ +| Argument | Type | Description | +| ---------- | ------------------- | --------------------------------- | +| `networkProtocol` |
AbstractProtocol
| Protocol used by the SDK instance | +| `autoResubscribe` |
Boolean

(`true`) | Class which contains options | + +## networkProtocol + +The protocol used to connect to the Kuzzle instance. +It can be one of the following available protocols: + +- [WebSocket](/sdk/jvm/1/protocols/websocket) + +## Return + +The `Kuzzle` SDK instance. + +## Usage + +<<< ./snippets/constructor-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/constructor/snippets/constructor-java.java b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-java.java new file mode 100644 index 00000000..4b03b113 --- /dev/null +++ b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-java.java @@ -0,0 +1 @@ +Kuzzle kuzzle = new Kuzzle(new WebSocket("kuzzle")); diff --git a/doc/1/core-classes/kuzzle/constructor/snippets/constructor-java.test.yml b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-java.test.yml new file mode 100644 index 00000000..7c079213 --- /dev/null +++ b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-java.test.yml @@ -0,0 +1,8 @@ +--- +name: java-kuzzle#constructor +description: Creates a new Kuzzle instance +hooks: + before: + after: +template: without-ctor +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/constructor/snippets/constructor-kotlin.kt b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-kotlin.kt new file mode 100644 index 00000000..705f5df9 --- /dev/null +++ b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-kotlin.kt @@ -0,0 +1 @@ +val kuzzle: Kuzzle = Kuzzle(WebSocket("kuzzle")) diff --git a/doc/1/core-classes/kuzzle/constructor/snippets/constructor-kotlin.test.yml b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-kotlin.test.yml new file mode 100644 index 00000000..0037cf17 --- /dev/null +++ b/doc/1/core-classes/kuzzle/constructor/snippets/constructor-kotlin.test.yml @@ -0,0 +1,8 @@ +--- +name: kotlin-kuzzle#constructor +description: Creates a new Kuzzle instance +hooks: + before: + after: +template: without-ctor +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/disconnect/index.md b/doc/1/core-classes/kuzzle/disconnect/index.md new file mode 100644 index 00000000..a212d276 --- /dev/null +++ b/doc/1/core-classes/kuzzle/disconnect/index.md @@ -0,0 +1,41 @@ +--- +code: true +type: page +title: disconnect +description: Disconnects the SDK from Kuzzle +--- + +# Disconnect + +Closes the current connection to Kuzzle. + +Disconnects the SDK from the Kuzzle server using the underlying protocol `disconnect` method. + +:::: tabs +::: tab Java + +## Arguments + +```java +public void disconnect() +``` + +## Usage + +<<< ./snippets/disconnect-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun disconnect() +``` + +## Usage + +<<< ./snippets/disconnect-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-java.java b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-java.java new file mode 100644 index 00000000..e7a7f4d6 --- /dev/null +++ b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-java.java @@ -0,0 +1 @@ +kuzzle.disconnect(); diff --git a/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-java.test.yml b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-java.test.yml new file mode 100644 index 00000000..a9d9fe19 --- /dev/null +++ b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-java.test.yml @@ -0,0 +1,8 @@ +--- +name: kuzzle#Disconnect +description: Disconnects the SDK to Kuzzle +hooks: + before: + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-kotlin.kt b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-kotlin.kt new file mode 100644 index 00000000..ea685e8b --- /dev/null +++ b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-kotlin.kt @@ -0,0 +1 @@ +kuzzle.disconnect() diff --git a/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-kotlin.test.yml b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-kotlin.test.yml new file mode 100644 index 00000000..a9d9fe19 --- /dev/null +++ b/doc/1/core-classes/kuzzle/disconnect/snippets/disconnect-kotlin.test.yml @@ -0,0 +1,8 @@ +--- +name: kuzzle#Disconnect +description: Disconnects the SDK to Kuzzle +hooks: + before: + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/index.md b/doc/1/core-classes/kuzzle/index.md new file mode 100644 index 00000000..b6873810 --- /dev/null +++ b/doc/1/core-classes/kuzzle/index.md @@ -0,0 +1,7 @@ +--- +code: false +type: branch +order: 100 +title: Kuzzle +description: Kuzzle class +--- diff --git a/doc/1/core-classes/kuzzle/query/index.md b/doc/1/core-classes/kuzzle/query/index.md new file mode 100644 index 00000000..27e3a08b --- /dev/null +++ b/doc/1/core-classes/kuzzle/query/index.md @@ -0,0 +1,95 @@ +--- +code: true +type: page +title: Query +description: Base method to send API query to Kuzzle +--- + +# query + +Base method used to send queries to Kuzzle, following the [API Documentation](/core/2/api). + +:::warning +This is a low-level method, exposed to allow advanced SDK users to bypass high-level methods. +::: + +:::: tabs +::: tab Java + +## Arguments + +```java +public CompletableFuture query( + ConcurrentHashMap query) + throws InternalException, NotConnectedException +``` + +
+ +| Argument | Type | Description | +| --------- | ----------------- | ---------------------- | +| `query` |
ConcurrentHashMap
| API request | + +### query + +All properties necessary for the Kuzzle API can be added in the query object. +The following properties are the most common. + +| Property | Type | Description | +| ------------ | ----------------- | ---------------------------------------- | +| `controller` |
String
| Controller name (mandatory) | +| `action` |
String
| Action name (mandatory) | +| `body` |
ConcurrentHashMap
| Query body for this action | +| `index` |
String
| Index name for this action | +| `collection` |
String
| Collection name for this action | +| `_id` |
String
| id for this action | +| `volatile` |
ConcurrentHashMap
| Additional information to send to Kuzzle | + +## Returns + +Returns a [Response](/sdk/jvm/1/core-classes/response) object which represents a raw Kuzzle API response. See the [API Documentation](/core/2/api). + +## Usage + +<<< ./snippets/query-java.java + +::: +::: tab Kotlin + +## Arguments + +```kotlin +fun query(query: ConcurrentHashMap): CompletableFuture +``` + +
+ +| Argument | Type | Description | +| --------- | ----------------- | ---------------------- | +| `query` |
ConcurrentHashMap
| API request | + +### query + +All properties necessary for the Kuzzle API can be added in the query object. +The following properties are the most common. + +| Property | Type | Description | +| ------------ | ----------------- | ---------------------------------------- | +| `controller` |
String
| Controller name (mandatory) | +| `action` |
String
| Action name (mandatory) | +| `body` |
ConcurrentHashMap
| Query body for this action | +| `index` |
String
| Index name for this action | +| `collection` |
String
| Collection name for this action | +| `_id` |
String
| id for this action | +| `volatile` |
ConcurrentHashMap
| Additional information to send to Kuzzle | + +## Returns + +Returns a [Response](/sdk/jvm/1/core-classes/response) object which represents a raw Kuzzle API response. See the [API Documentation](/core/2/api). + +## Usage + +<<< ./snippets/query-kotlin.kt + +::: +:::: \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/query/snippets/query-java.java b/doc/1/core-classes/kuzzle/query/snippets/query-java.java new file mode 100644 index 00000000..76e76e85 --- /dev/null +++ b/doc/1/core-classes/kuzzle/query/snippets/query-java.java @@ -0,0 +1,13 @@ +ConcurrentHashMap query = new ConcurrentHashMap<>(); +query.put("controller", "document"); +query.put("action", "create"); +query.put("index", "nyc-open-data"); +query.put("collection", "yellow-taxi"); +query.put("_id", "my-custom-document-id"); +query.put("refresh", "wait_for"); +ConcurrentHashMap body = new ConcurrentHashMap<>(); +body.put("trip_distance", 4.23); +body.put("passenger_count", 2); +query.put("body", body); + +Response res = kuzzle.query(query).get(); diff --git a/doc/1/core-classes/kuzzle/query/snippets/query-java.test.yml b/doc/1/core-classes/kuzzle/query/snippets/query-java.test.yml new file mode 100644 index 00000000..87fbb5b7 --- /dev/null +++ b/doc/1/core-classes/kuzzle/query/snippets/query-java.test.yml @@ -0,0 +1,11 @@ +--- +name: kuzzle#Query +description: Sends a request to Kuzzle API +hooks: + before: | + curl -X POST kuzzle:7512/nyc-open-data/_create + curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi + curl -X DELETE kuzzle:7512/nyc-open-data/yellow-taxi/my-custom-document-id + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/kuzzle/query/snippets/query-kotlin.kt b/doc/1/core-classes/kuzzle/query/snippets/query-kotlin.kt new file mode 100644 index 00000000..83be6d8e --- /dev/null +++ b/doc/1/core-classes/kuzzle/query/snippets/query-kotlin.kt @@ -0,0 +1,14 @@ +val query: ConcurrentHashMap = ConcurrentHashMap().apply { + put("controller", "document") + put("action", "create") + put("index", "nyc-open-data") + put("collection", "yellow-taxi") + put("_id", "my-custom-document-id") + put("refresh", "wait_for") + put("body", ConcurrentHashMap().apply { + put("trip_distance", 4.23) + put("passenger_count", 2) + }) +} + +val res: Response = kuzzle.query(query).get() diff --git a/doc/1/core-classes/kuzzle/query/snippets/query-kotlin.test.yml b/doc/1/core-classes/kuzzle/query/snippets/query-kotlin.test.yml new file mode 100644 index 00000000..87fbb5b7 --- /dev/null +++ b/doc/1/core-classes/kuzzle/query/snippets/query-kotlin.test.yml @@ -0,0 +1,11 @@ +--- +name: kuzzle#Query +description: Sends a request to Kuzzle API +hooks: + before: | + curl -X POST kuzzle:7512/nyc-open-data/_create + curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi + curl -X DELETE kuzzle:7512/nyc-open-data/yellow-taxi/my-custom-document-id + after: +template: default +expected: Success \ No newline at end of file diff --git a/doc/1/core-classes/response/index.md b/doc/1/core-classes/response/index.md new file mode 100644 index 00000000..020ffc47 --- /dev/null +++ b/doc/1/core-classes/response/index.md @@ -0,0 +1,7 @@ +--- +code: true +type: branch +title: Response +description: Response object documentation +order: 0 +--- \ No newline at end of file diff --git a/doc/1/core-classes/response/introduction/index.md b/doc/1/core-classes/response/introduction/index.md new file mode 100644 index 00000000..270c20dd --- /dev/null +++ b/doc/1/core-classes/response/introduction/index.md @@ -0,0 +1,30 @@ +--- +code: false +type: page +title: Introduction +description: Response object description +order: 0 +--- + +## Response + +`Response` is a **serializable** class representing a raw Kuzzle response. + +## Properties + +| Property | Type | Description | +|--- |--- |--- | +| `action` |
String
| Executed Kuzzle API controller's action | +| `collection` |
String
| Impacted collection | +| `controller` |
String
| Executed Kuzzle API controller | +| `error` |
[ErrorResponse](/sdk/jvm/1/core-classes/error-response)
| Error object (null if the request finished successfully) | +| `index` |
String
| Impacted index | +| `protocol` |
String
| Network protocol at the origin of the real-time notification | +| `requestId` |
String
| Request unique identifier | +| `result` |
Object
| Response payload (depends on the executed API action) | +| `room` |
String
| Room identifier (realtime only) | +| `scope` |
String
| Document scope ("in" or "out", realtime only) | +| `state` |
String
| Document state (realtime only) | +| `status` |
int
| Response status, following HTTP status codes | +| `timestamp` |
Long
| Notification timestamp (UTC) | +| `volatile` |
ConcurrentHashMap
| Volatile data | diff --git a/doc/1/index.md b/doc/1/index.md new file mode 100644 index 00000000..9f545322 --- /dev/null +++ b/doc/1/index.md @@ -0,0 +1,7 @@ +--- +code: false +type: root +order: 0 +title: Jvm SDK v1.x +description: Jvm SDK v1.x +--- diff --git a/doc/doc.sh b/doc/doc.sh new file mode 100755 index 00000000..0ceef59c --- /dev/null +++ b/doc/doc.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +set -eu + +DOC_VERSION=1 +DOC_PATH=/sdk/jvm/1 +PWD=$(dirname $(readlink -f $0)) +FMWKDIR="$PWD/framework" +FMWKTARGET="$FMWKDIR/src$DOC_PATH" +VUEPRESS="$FMWKDIR/node_modules/.bin/vuepress" + +# Used by vuepress +export DOC_DIR="$PWD/${DOC_VERSION}" +export SITE_BASE=$DOC_PATH/ + +# Used to specify --no-cache for example +ARGS=${2:-""} + +if [ ! -d "$DOC_DIR" ] +then + echo "Cannot find documentation directory: $DOC_DIR" + exit 1 +fi + +case $1 in + prepare) + echo "Clone documentation framework" + rm -rf $FMWKDIR + git clone --depth 10 --single-branch --branch master https://github.com/kuzzleio/documentation.git $FMWKDIR + + echo "Link local doc for dead links checking" + rm $FMWKTARGET + ln -s ${DOC_DIR} $FMWKTARGET + + echo "Install dependencies" + npm --prefix $FMWKDIR ci + ;; + + dev) + $VUEPRESS dev $DOC_DIR/ $ARGS + ;; + + build) + $VUEPRESS build $DOC_DIR/ $ARGS + ;; + + build-netlify) + export SITE_BASE="/" + $VUEPRESS build $DOC_DIR/ $ARGS + ;; + + upload) + aws s3 sync $DOC_DIR/.vuepress/dist s3://$S3_BUCKET$SITE_BASE + ;; + + cloudfront) + aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "$SITE_BASE*" + ;; + + *) + echo "Usage : $0 " + exit 1 + ;; +esac diff --git a/doc/frontmatter-errors.json b/doc/frontmatter-errors.json new file mode 100644 index 00000000..ef052e77 --- /dev/null +++ b/doc/frontmatter-errors.json @@ -0,0 +1,22 @@ +{ + "/controllers/auth/": [ + { + "fix": { + "type": "page" + }, + "error": "MISSING_KEY", + "key": "type" + }, + { + "error": "MISSING_KEY", + "key": "title" + }, + { + "fix": { + "code": true + }, + "error": "MISSING_KEY", + "key": "code" + } + ] +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..58c3eb87 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1627 @@ +{ + "name": "sdk-dart", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@oclif/command": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.6.1.tgz", + "integrity": "sha512-pvmMmfGn+zm4e4RwVw63mg9sIaqKqmVsFbImQoUrCO/43UmWzoSHWNXKdgEGigOezWrkZfFucaeZcSbp149OWg==", + "requires": { + "@oclif/config": "^1.15.1", + "@oclif/errors": "^1.2.2", + "@oclif/parser": "^3.8.3", + "@oclif/plugin-help": "^3", + "debug": "^4.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "@oclif/plugin-help": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.1.0.tgz", + "integrity": "sha512-orSWpXGlJaX16eSjAtI8scA8QhrjQOaCSHodEx52t18JKbIVzG8jcngugyWAOB/V4jhPl0rdiVk9XFsaIIiG2g==", + "requires": { + "@oclif/command": "^1.5.20", + "@oclif/config": "^1.15.1", + "chalk": "^2.4.1", + "indent-string": "^4.0.0", + "lodash.template": "^4.4.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0", + "widest-line": "^2.0.1", + "wrap-ansi": "^4.0.0" + } + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "@oclif/config": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.15.1.tgz", + "integrity": "sha512-GdyHpEZuWlfU8GSaZoiywtfVBsPcfYn1KuSLT1JTfvZGpPG6vShcGr24YZ3HG2jXUFlIuAqDcYlTzOrqOdTPNQ==", + "requires": { + "@oclif/errors": "^1.0.0", + "@oclif/parser": "^3.8.0", + "debug": "^4.1.1", + "tslib": "^1.9.3" + } + }, + "@oclif/errors": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.2.2.tgz", + "integrity": "sha512-Eq8BFuJUQcbAPVofDxwdE0bL14inIiwt5EaKRVY9ZDIG11jwdXZqiQEECJx0VfnLyUZdYfRd/znDI/MytdJoKg==", + "requires": { + "clean-stack": "^1.3.0", + "fs-extra": "^7.0.0", + "indent-string": "^3.2.0", + "strip-ansi": "^5.0.0", + "wrap-ansi": "^4.0.0" + } + }, + "@oclif/linewrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz", + "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==" + }, + "@oclif/parser": { + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.5.tgz", + "integrity": "sha512-yojzeEfmSxjjkAvMRj0KzspXlMjCfBzNRPkWw8ZwOSoNWoJn+OCS/m/S+yfV6BvAM4u2lTzX9Y5rCbrFIgkJLg==", + "requires": { + "@oclif/errors": "^1.2.2", + "@oclif/linewrap": "^1.0.0", + "chalk": "^2.4.2", + "tslib": "^1.9.3" + } + }, + "@oclif/plugin-help": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.3.tgz", + "integrity": "sha512-bGHUdo5e7DjPJ0vTeRBMIrfqTRDBfyR5w0MP41u0n3r7YG5p14lvMmiCXxi6WDaP2Hw5nqx3PnkAIntCKZZN7g==", + "requires": { + "@oclif/command": "^1.5.13", + "chalk": "^2.4.1", + "indent-string": "^4.0.0", + "lodash.template": "^4.4.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0", + "widest-line": "^2.0.1", + "wrap-ansi": "^4.0.0" + }, + "dependencies": { + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "@oclif/screen": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz", + "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "requires": { + "any-observable": "^0.3.0" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/listr": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@types/listr/-/listr-0.14.2.tgz", + "integrity": "sha512-wCipMbQr3t2UHTm90LldVp+oTBj1TX6zvpkCJcWS4o8nn6kS8SN93oUvKJAgueIRZ5M36yOlFmScqBxYH8Ajig==", + "requires": { + "@types/node": "*", + "rxjs": "^6.5.1" + } + }, + "@types/node": { + "version": "14.0.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", + "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "requires": { + "type-fest": "^0.11.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-stack": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", + "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-progress": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.8.2.tgz", + "integrity": "sha512-qRwBxLldMSfxB+YGFgNRaj5vyyHe1yMpVeDL79c+7puGujdKJHQHydgqXDcrkvQgJ5U/d3lpf6vffSoVVUftVQ==", + "requires": { + "colors": "^1.1.2", + "string-width": "^4.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "cli-ux": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.4.6.tgz", + "integrity": "sha512-EeiS2TzEndRVknCqE+8Ri8g0bsP617a1nq6n+3Trwft1JCDzyUNlX2J1fl7fwTgRPWtmBmiF6xIyueL5YGs65g==", + "requires": { + "@oclif/command": "^1.6.0", + "@oclif/errors": "^1.2.1", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.3", + "ansi-escapes": "^4.3.0", + "ansi-styles": "^4.2.0", + "cardinal": "^2.1.1", + "chalk": "^2.4.1", + "clean-stack": "^2.0.0", + "cli-progress": "^3.4.0", + "extract-stack": "^1.0.0", + "fs-extra": "^7.0.1", + "hyperlinker": "^1.0.0", + "indent-string": "^4.0.0", + "is-wsl": "^1.1.0", + "js-yaml": "^3.13.1", + "lodash": "^4.17.11", + "natural-orderby": "^2.0.1", + "object-treeify": "^1.1.4", + "password-prompt": "^1.1.2", + "semver": "^5.6.0", + "string-width": "^3.1.0", + "strip-ansi": "^5.1.0", + "supports-color": "^5.5.0", + "supports-hyperlinks": "^1.0.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "execa": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", + "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "extract-stack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-1.0.0.tgz", + "integrity": "sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo=" + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "requires": { + "pump": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" + }, + "hyperlinker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", + "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "kuzdoc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/kuzdoc/-/kuzdoc-1.2.2.tgz", + "integrity": "sha512-QXw4dVIh4dRoD/9Vz9tbpfKNT9Y0AEORJyRHIwKuHaxH65Ccr7KHwxSTbJokK/PV4PebRDO96sPodEc/4NrxbQ==", + "requires": { + "@oclif/command": "^1.5.19", + "@oclif/config": "^1.13.3", + "@oclif/plugin-help": "^2.2.3", + "@types/listr": "^0.14.2", + "axios": "^0.19.0", + "cli-ux": "^5.4.1", + "execa": "^4.0.0", + "express": "^4.17.1", + "listr": "^0.14.3", + "tslib": "^1.10.0", + "yaml": "^1.7.2" + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "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" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + } + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "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" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "natural-orderby": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", + "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + }, + "dependencies": { + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + } + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-treeify": { + "version": "1.1.25", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.25.tgz", + "integrity": "sha512-6Abx0xlXDnYd50JkQefvoIly3jWOu8/PqH4lh8p2/aMFEx5TjsUGHt0H9NHfzt+pCwOhpPgNYofD8e2YywIXig==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "password-prompt": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.2.tgz", + "integrity": "sha512-bpuBhROdrhuN3E7G/koAju0WjVw9/uQOG5Co5mokNj0MiOSBVZS1JTwM4zl55hu0WFmIEFvO9cU9sJQiBIYeIA==", + "requires": { + "ansi-escapes": "^3.1.0", + "cross-spawn": "^6.0.5" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + } + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "requires": { + "esprima": "~4.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + } + } + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "requires": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "requires": { + "string-width": "^2.1.1" + } + }, + "wrap-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", + "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..3d7b99c5 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "sdk-jvm", + "scripts": { + "doc-prepare": "kuzdoc framework:install", + "doc-dev": "kuzdoc repo:dev -d /sdk/jvm/1/ -v 1", + "doc-build": "kuzdoc repo:build -d /sdk/jvm/1/ -v 1", + "doc-upload": "kuzdoc repo:deploy -d /sdk/jvm/1/ -v 1", + "doc-cloudfront": "kuzdoc repo:cloudfront -d /sdk/jvm/1/*", + "doc-deploy": "npm run doc-upload && npm run doc-cloudfront", + "doc-netlify": "npm run doc-prepare && kuzdoc repo:build -d / -v 1" + }, + "dependencies": { + "kuzdoc": "^1.2.2" + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 926c3014..3656d608 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1 +1 @@ -rootProject.name = "sdk-kotlin" +rootProject.name = "sdk-jvm" diff --git a/src/main/kotlin/io/kuzzle/sdk/Kuzzle.kt b/src/main/kotlin/io/kuzzle/sdk/Kuzzle.kt index 65ebc1e0..4e3ce5dc 100644 --- a/src/main/kotlin/io/kuzzle/sdk/Kuzzle.kt +++ b/src/main/kotlin/io/kuzzle/sdk/Kuzzle.kt @@ -1,10 +1,12 @@ package io.kuzzle.sdk -import io.kuzzle.sdk.coreClasses.exceptions.KuzzleException +import io.kuzzle.sdk.controllers.RealtimeController +import io.kuzzle.sdk.coreClasses.exceptions.ApiErrorException import io.kuzzle.sdk.coreClasses.exceptions.KuzzleExceptionCode import io.kuzzle.sdk.coreClasses.exceptions.NotConnectedException import io.kuzzle.sdk.coreClasses.json.JsonSerializer import io.kuzzle.sdk.coreClasses.maps.KuzzleMap +import io.kuzzle.sdk.coreClasses.responses.Response import io.kuzzle.sdk.protocol.AbstractProtocol import io.kuzzle.sdk.protocol.ProtocolState import java.util.* @@ -12,35 +14,74 @@ import java.util.concurrent.CompletableFuture import java.util.concurrent.ConcurrentHashMap import kotlin.collections.HashMap -class Kuzzle(private val protocol: AbstractProtocol) { - private val queries: HashMap> = HashMap() - private val instanceId: String - private val version: String = "3" - private val sdkName: String = "java@$version" - var authenticationToken: String? = null - - private fun onMessageReceived(message: String) { - val json = JsonSerializer.deserialize(message) - queries[json["requestId"]]?.complete(message as Any) - queries.remove(json["requestId"]) - } +class Kuzzle { + val protocol: AbstractProtocol + val autoResubscribe: Boolean + private val queries: HashMap> = HashMap() + val instanceId: String + private val version: String = "1" + private val sdkName: String = "jvm@$version" + private var authenticationToken: String? = null + val realtimeController: RealtimeController - init { + @JvmOverloads + constructor(protocol: AbstractProtocol, autoResubscribe: Boolean = true) { + this.protocol = protocol + this.autoResubscribe = autoResubscribe + instanceId = UUID.randomUUID().toString() + realtimeController = RealtimeController(this) // @TODO Create enums for events protocol.addListener("messageReceived", ::onMessageReceived) - instanceId = UUID.randomUUID().toString() + protocol.addListener("networkStateChange", ::onNetworkStateChange) + } + + private fun onMessageReceived(message: String?) { + val response = Response().apply { + fromMap(JsonSerializer.deserialize(message) as ConcurrentHashMap) + } + + if (queries.size == 0 || (queries.size != 0 && (response.room == null || queries[response.room!!] == null))) { + protocol.trigger("unhandledResponse", message) + return + } + + if (response.error == null) { + queries[response.requestId]?.complete(response) + queries.remove(response.requestId) + return + } + + val error = JsonSerializer.deserialize(response.error.toString()) + if (error["id"] == null + || error["id"]!! != "security.token.expired") { + queries[response.requestId]?.completeExceptionally(ApiErrorException(response)) + queries.remove(response.requestId) + return + } + + protocol.trigger("tokenExpired") + } + + private fun onNetworkStateChange(state: String?) { + if (state == ProtocolState.OPEN.toString() && autoResubscribe) { + realtimeController.renewSubscriptions() + } } fun connect() { protocol.connect() } - fun query(query: ConcurrentHashMap): CompletableFuture { + fun disconnect() { + protocol.disconnect() + } + + fun query(query: ConcurrentHashMap): CompletableFuture { if (protocol.state == ProtocolState.CLOSE) { throw NotConnectedException() } - val futureRes: CompletableFuture = CompletableFuture() + val futureRes: CompletableFuture = CompletableFuture() val requestId = UUID.randomUUID().toString() val queryMap = KuzzleMap.from(query) diff --git a/src/main/kotlin/io/kuzzle/sdk/controllers/BaseController.kt b/src/main/kotlin/io/kuzzle/sdk/controllers/BaseController.kt new file mode 100644 index 00000000..0f4eeeef --- /dev/null +++ b/src/main/kotlin/io/kuzzle/sdk/controllers/BaseController.kt @@ -0,0 +1,5 @@ +package io.kuzzle.sdk.controllers + +import io.kuzzle.sdk.Kuzzle + +open class BaseController(protected val kuzzle: Kuzzle) diff --git a/src/main/kotlin/io/kuzzle/sdk/controllers/RealtimeController.kt b/src/main/kotlin/io/kuzzle/sdk/controllers/RealtimeController.kt new file mode 100644 index 00000000..6612a29e --- /dev/null +++ b/src/main/kotlin/io/kuzzle/sdk/controllers/RealtimeController.kt @@ -0,0 +1,188 @@ +package io.kuzzle.sdk.controllers; + +import io.kuzzle.sdk.Kuzzle +import io.kuzzle.sdk.coreClasses.json.JsonSerializer +import io.kuzzle.sdk.coreClasses.maps.KuzzleMap +import io.kuzzle.sdk.coreClasses.responses.Response +import io.kuzzle.sdk.handlers.NotificationHandler +import io.kuzzle.sdk.protocol.ProtocolState +import java.util.* +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentHashMap +import java.util.function.Consumer + +class RealtimeController(kuzzle: Kuzzle) : BaseController(kuzzle) { + private inner class Subscription( + val index: String, + val collection: String, + val filter: ConcurrentHashMap, + val handler: (Response) -> Unit, + val scope: String, + val users: String, + val subscribeToSelf: Boolean, + val volatile: ConcurrentHashMap) + + init { + kuzzle.protocol.addListener("unhandledResponse") { + val response = Response().apply { + fromMap(JsonSerializer.deserialize(it) as ConcurrentHashMap) + } + + if (response.error != null && response.error!!.id.equals("security.token.expired")) { + kuzzle.protocol.trigger("tokenExpired") + } else { + var sdkInstanceId = "" + if (response.Volatile != null) { + sdkInstanceId = response.Volatile!!["sdkInstanceId"].toString() + } + + val subs: ArrayList? = currentSubscriptions[response.room] + if (subs != null) { + val instanceId = sdkInstanceId + subs.forEach { + if (instanceId == kuzzle.instanceId && it.subscribeToSelf || instanceId != kuzzle.instanceId) { + it.handler(response) + } + } + } + } + } + + kuzzle.protocol.addListener("networkStateChange") { + if (it == ProtocolState.CLOSE.toString()) { + currentSubscriptions.clear() + } + } + } + + fun count(roomId: String): CompletableFuture { + return kuzzle + .query(KuzzleMap().apply { + put("controller", "realtime") + put("action", "count") + put("body", KuzzleMap().put("roomId", roomId)) + }) + .thenApplyAsync { response -> (response.result as KuzzleMap?)!!.getNumber("count")?.toInt() } + } + + fun publish(index: String, collection: String, message: ConcurrentHashMap): CompletableFuture { + return kuzzle + .query(KuzzleMap().apply { + put("controller", "realtime") + put("action", "publish") + put("index", index) + put("collection", collection) + put("body", KuzzleMap().put("message", message)) + }) + .thenApplyAsync { null } + } + + fun renewSubscriptions() { + for ((key, value) in subscriptionsCache) { + (value).forEach(Consumer { subscription: Subscription -> + subscribe( + subscription.index, + subscription.collection, + subscription.filter, + subscription.scope, + subscription.users, + subscription.subscribeToSelf, + subscription.volatile, + subscription.handler + ) + }) + subscriptionsCache[key]!!.clear() + } + } + + fun subscribe( + index: String?, + collection: String?, + filters: ConcurrentHashMap, + scope: String = "all", + users: String = "all", + subscribeToSelf: Boolean = true, + volatiles: ConcurrentHashMap = ConcurrentHashMap(), + handler: (Response) -> Unit): CompletableFuture { + val query: KuzzleMap = KuzzleMap().apply { + put("controller", "realtime") + put("action", "subscribe") + put("index", index) + put("collection", collection) + put("body", filters) + put("volatile", volatiles) + } + return kuzzle + .query(query) + .thenApplyAsync { response -> + val channel = (response.result as ConcurrentHashMap<*, *>)["channel"].toString() + val subscription = Subscription( + index!!, + collection!!, + filters, + handler, + scope, + users, + subscribeToSelf, + volatiles) + if (currentSubscriptions[channel] == null) { + val item = ArrayList() + item.add(subscription) + currentSubscriptions[channel] = item + subscriptionsCache[channel] = item + } else { + currentSubscriptions[channel]!!.add(subscription) + subscriptionsCache[channel]!!.add(subscription) + } + (response.result as ConcurrentHashMap<*, *>)["roomId"].toString() + } + } + + /** + For JAVA + */ + @JvmOverloads + fun subscribe( + index: String?, + collection: String?, + filters: ConcurrentHashMap, + scope: String = "all", + users: String = "all", + subscribeToSelf: Boolean = true, + volatiles: ConcurrentHashMap = ConcurrentHashMap(), + handler: NotificationHandler): CompletableFuture { + return subscribe( + index, + collection, + filters, + scope, + users, + subscribeToSelf, + volatiles) { + handler.run(it) + } + } + + fun unsubscribe(roomId: String): CompletableFuture { + return kuzzle + .query(KuzzleMap().apply { + put("controller", "realtime") + put("action", "unsubscribe") + put("body", KuzzleMap().put("roomId", roomId)) + }) + .thenApplyAsync { _ -> + var subs: ArrayList? = currentSubscriptions[roomId] + if (subs != null) { + currentSubscriptions[roomId]!!.clear() + } + subs = subscriptionsCache[roomId] + if (subs != null) { + subscriptionsCache[roomId]!!.clear() + } + null + } + } + + private val currentSubscriptions = ConcurrentHashMap>() + private val subscriptionsCache = ConcurrentHashMap>() +} diff --git a/src/main/kotlin/io/kuzzle/sdk/coreClasses/exceptions/ApiErrorException.kt b/src/main/kotlin/io/kuzzle/sdk/coreClasses/exceptions/ApiErrorException.kt new file mode 100644 index 00000000..696d8475 --- /dev/null +++ b/src/main/kotlin/io/kuzzle/sdk/coreClasses/exceptions/ApiErrorException.kt @@ -0,0 +1,37 @@ +package io.kuzzle.sdk.coreClasses.exceptions; + +import io.kuzzle.sdk.coreClasses.responses.Response + +/** + * Passed to async tasks when an API request returns an error. + */ +class ApiErrorException : KuzzleException { + companion object { + private const val serialVersionUID = 666379398727075901L + } + + /** + * Kuzzle API stack trace + */ + var stack: String? = null + private set + + /** + * Kuzzle API error unique identifier + */ + var id: String? = null + private set + + /** + * Initializes a new instance of the ApiErrorException + * + * @param response Kuzzle API Response. + */ + constructor(response: Response) : + super(response.error?.message, response.status) { + if (response.error != null) { + this.stack = response.error?.stack; + this.id = response.error?.id; + } + } +} diff --git a/src/main/kotlin/io/kuzzle/sdk/coreClasses/responses/Response.kt b/src/main/kotlin/io/kuzzle/sdk/coreClasses/responses/Response.kt index f7eab109..684bb5cf 100644 --- a/src/main/kotlin/io/kuzzle/sdk/coreClasses/responses/Response.kt +++ b/src/main/kotlin/io/kuzzle/sdk/coreClasses/responses/Response.kt @@ -6,6 +6,9 @@ import io.kuzzle.sdk.coreClasses.maps.Serializable import java.util.concurrent.ConcurrentHashMap class Response : Serializable { + var mapResponse: ConcurrentHashMap? = null + private set + var room: String? = null /** @@ -81,6 +84,8 @@ class Response : Serializable { override fun fromMap(map: ConcurrentHashMap?) { if (map == null) return + mapResponse = map + val kuzzleMap = KuzzleMap(map) room = kuzzleMap.getString("room") result = kuzzleMap.get("result") @@ -93,7 +98,7 @@ class Response : Serializable { if (requestId == null) { throw Exception(KuzzleExceptionCode.MISSING_REQUESTID.message) } - status = kuzzleMap.optNumber("status", 0) as Int + status = (kuzzleMap.optNumber("status", 0) as com.google.gson.internal.LazilyParsedNumber).toInt() controller = kuzzleMap.getString("controller") action = kuzzleMap.getString("action") index = kuzzleMap.getString("index") @@ -104,7 +109,7 @@ class Response : Serializable { state = kuzzleMap.getString("state") timestamp = when(kuzzleMap.getNumber("timestamp")) { null -> null - else -> kuzzleMap.getNumber("timestamp") as Long + else -> (kuzzleMap.getNumber("timestamp") as com.google.gson.internal.LazilyParsedNumber).toLong() } type = kuzzleMap.getString("type") } @@ -130,4 +135,8 @@ class Response : Serializable { return map } + + override fun toString(): String { + return mapResponse.toString() + } } \ No newline at end of file diff --git a/src/main/kotlin/io/kuzzle/sdk/events/EventManager.kt b/src/main/kotlin/io/kuzzle/sdk/events/EventManager.kt index 40465f59..cc25265b 100644 --- a/src/main/kotlin/io/kuzzle/sdk/events/EventManager.kt +++ b/src/main/kotlin/io/kuzzle/sdk/events/EventManager.kt @@ -1,13 +1,13 @@ package io.kuzzle.sdk.events open class EventManager { - private val listeners: HashMap Unit> = HashMap() + private val listeners: HashMap Unit> = HashMap() - fun addListener(event: String, listener: (String) -> Unit) { + fun addListener(event: String, listener: (String?) -> Unit) { listeners[event] = listener } - fun trigger(event: String, message: String) { + fun trigger(event: String, message: String? = null) { listeners[event]?.invoke(message) } } \ No newline at end of file diff --git a/src/main/kotlin/io/kuzzle/sdk/handlers/NotificationHandler.kt b/src/main/kotlin/io/kuzzle/sdk/handlers/NotificationHandler.kt new file mode 100644 index 00000000..0e9e71bd --- /dev/null +++ b/src/main/kotlin/io/kuzzle/sdk/handlers/NotificationHandler.kt @@ -0,0 +1,11 @@ +package io.kuzzle.sdk.handlers + +import io.kuzzle.sdk.coreClasses.responses.Response + +/** + * Interface to be used with realtime:subscribe + * to make it more usable in JAVA + */ +interface NotificationHandler { + fun run(notification: Response) +} diff --git a/src/main/kotlin/io/kuzzle/sdk/protocol/ProtocolState.kt b/src/main/kotlin/io/kuzzle/sdk/protocol/ProtocolState.kt index ab880076..a3c38211 100644 --- a/src/main/kotlin/io/kuzzle/sdk/protocol/ProtocolState.kt +++ b/src/main/kotlin/io/kuzzle/sdk/protocol/ProtocolState.kt @@ -2,6 +2,6 @@ package io.kuzzle.sdk.protocol enum class ProtocolState { CLOSE, // The network protocol does not accept requests. - OPEN - // The network protocol accepts new requests. + OPEN, // The network protocol accepts new requests. + RECONNECTING // The nerwork protocol is trying to reconnect } \ No newline at end of file diff --git a/src/main/kotlin/io/kuzzle/sdk/protocol/WebSocket.kt b/src/main/kotlin/io/kuzzle/sdk/protocol/WebSocket.kt index 8d204f63..5007c139 100644 --- a/src/main/kotlin/io/kuzzle/sdk/protocol/WebSocket.kt +++ b/src/main/kotlin/io/kuzzle/sdk/protocol/WebSocket.kt @@ -15,8 +15,10 @@ import io.ktor.http.cio.websocket.readText import io.ktor.util.KtorExperimentalAPI import io.kuzzle.sdk.coreClasses.json.JsonSerializer import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.channels.receiveOrNull import kotlinx.coroutines.launch +import java.io.IOException +import java.net.ConnectException +import java.net.SocketException import java.util.concurrent.CompletableFuture import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue @@ -24,6 +26,15 @@ import kotlin.concurrent.thread open class WebSocket : AbstractProtocol { protected open var ws: DefaultClientWebSocketSession? = null + private val host: String + private val port: Int + private val isSsl: Boolean + private val queue: ConcurrentLinkedQueue = ConcurrentLinkedQueue() + override var state: ProtocolState = ProtocolState.CLOSE + private val autoReconnect: Boolean + private val reconnectionDelay: Long + private val reconnectionRetries: Long + private var retryCount: Long = 0 @KtorExperimentalAPI protected open var client = HttpClient { @@ -33,17 +44,33 @@ open class WebSocket : AbstractProtocol { acceptContentTypes += ContentType("application", "json") } } - private val host: String - private val port: Int - private val isSsl: Boolean - private val queue: ConcurrentLinkedQueue = ConcurrentLinkedQueue() - override var state: ProtocolState = ProtocolState.CLOSE @JvmOverloads - constructor(host: String, port: Int = 7512, isSsl: Boolean = false) { + constructor( + host: String, + port: Int = 7512, + isSsl: Boolean = false, + autoReconnect: Boolean = true, + reconnectionDelay: Long = 1000, + reconnectionRetries: Long = 60) { this.host = host this.port = port this.isSsl = isSsl + this.autoReconnect = autoReconnect + this.reconnectionDelay = reconnectionDelay + this.reconnectionRetries = reconnectionRetries + } + + private fun tryToReconnect() { + if (retryCount < reconnectionRetries) { + retryCount++ + state = ProtocolState.RECONNECTING + trigger("networkStateChange", state.toString()) + Thread.sleep(reconnectionDelay) + thread(start = true) { + connect() + } + } } @KtorExperimentalAPI @@ -52,8 +79,8 @@ open class WebSocket : AbstractProtocol { val block: suspend DefaultClientWebSocketSession.() -> Unit = { ws = this // @TODO Create enums for events - super.trigger("networkStateChange", "open") state = ProtocolState.OPEN + trigger("networkStateChange", ProtocolState.OPEN.toString()) thread(start = true) { while (ws != null) { val payload = queue.poll() @@ -65,29 +92,53 @@ open class WebSocket : AbstractProtocol { } } wait.complete(null) - for (frame in incoming) { - when (frame) { - // @TODO Create enums for events - is Frame.Text -> super.trigger("messageReceived", frame.readText()) - // @TODO Create enums for events - is Frame.Binary -> super.trigger("messageReceived", frame.readBytes().toString()) + try { + for (frame in incoming) { + when (frame) { + // @TODO Create enums for events + is Frame.Text -> super.trigger("messageReceived", frame.readText()) + // @TODO Create enums for events + is Frame.Binary -> super.trigger("messageReceived", frame.readBytes().toString()) + } } + } catch (e: Exception) { + tryToReconnect() } + state = ProtocolState.CLOSE + trigger("networkStateChange", ProtocolState.CLOSE.toString()) ws = null } GlobalScope.launch { - if (isSsl) { - client.wss( - host = this@WebSocket.host, - port = this@WebSocket.port, - block = block - ) - } else { - client.ws( - host = this@WebSocket.host, - port = this@WebSocket.port, - block = block - ) + try { + if (isSsl) { + client.wss( + host = this@WebSocket.host, + port = this@WebSocket.port, + block = block + ) + } else { + client.ws( + host = this@WebSocket.host, + port = this@WebSocket.port, + block = block + ) + } + retryCount = 0 + // This thread is here to let JAVA run until the socket is closed + // In Kotlin this is handled by the block function above but for some reason in JAVA it is + // non blocking. + thread(start = true) { + while (true) {} + } + } catch (e: Exception) { + when (e) { + is ConnectException, + is SocketException, + is IOException -> { + tryToReconnect() + wait.complete(null) + } else -> throw e + } } } wait.get() @@ -95,6 +146,7 @@ open class WebSocket : AbstractProtocol { override fun disconnect() { state = ProtocolState.CLOSE + trigger("networkStateChange", ProtocolState.CLOSE.toString()) GlobalScope.launch { ws?.close() ws = null