From 4d0bdb27c1fc13d036755788ae931ff5571e5aba Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Fri, 15 Jan 2021 13:10:17 +0000 Subject: [PATCH 01/57] Reorganization --- .gitignore | 45 +- Jenkinsfile | 775 ------- avatar-default.png | Bin 0 -> 3377 bytes .dockerignore => build/.dockerignore | 2 + .gitattributes => build/.gitattributes | 0 build/.gitignore | 45 + Dockerfile => build/Dockerfile | 7 +- .../Dockerfile.aarch64 | 0 Dockerfile.armhf => build/Dockerfile.armhf | 0 LICENSE => build/LICENSE | 0 README.md => build/README.md | 0 .../package_versions.txt | 0 readme-vars.yml => build/readme-vars.yml | 0 build/root/app/.gitignore | 2 + {root => build/root}/app/add-peer | 0 build/root/app/package-lock.json | 1913 +++++++++++++++++ build/root/app/package.json | 33 + {root => build/root}/app/show-peer | 0 build/root/app/src/server.ts | 49 + build/root/app/tsconfig.json | 12 + build/root/app/tslint.json | 13 + {root => build/root}/defaults/Corefile | 0 {root => build/root}/defaults/peer.conf | 0 {root => build/root}/defaults/server.conf | 0 {root => build/root}/donate.txt | 0 .../root}/etc/cont-init.d/30-config | 0 .../root}/etc/services.d/coredns/run | 0 .../root}/etc/services.d/wireguard/run | 0 dappnode_package.json | 12 + docker-compose.yml | 26 + jenkins-vars.yml | 29 - 31 files changed, 2115 insertions(+), 848 deletions(-) delete mode 100644 Jenkinsfile create mode 100644 avatar-default.png rename .dockerignore => build/.dockerignore (65%) rename .gitattributes => build/.gitattributes (100%) create mode 100644 build/.gitignore rename Dockerfile => build/Dockerfile (93%) rename Dockerfile.aarch64 => build/Dockerfile.aarch64 (100%) rename Dockerfile.armhf => build/Dockerfile.armhf (100%) rename LICENSE => build/LICENSE (100%) rename README.md => build/README.md (100%) rename package_versions.txt => build/package_versions.txt (100%) rename readme-vars.yml => build/readme-vars.yml (100%) create mode 100644 build/root/app/.gitignore rename {root => build/root}/app/add-peer (100%) create mode 100644 build/root/app/package-lock.json create mode 100644 build/root/app/package.json rename {root => build/root}/app/show-peer (100%) create mode 100644 build/root/app/src/server.ts create mode 100644 build/root/app/tsconfig.json create mode 100644 build/root/app/tslint.json rename {root => build/root}/defaults/Corefile (100%) rename {root => build/root}/defaults/peer.conf (100%) rename {root => build/root}/defaults/server.conf (100%) rename {root => build/root}/donate.txt (100%) rename {root => build/root}/etc/cont-init.d/30-config (100%) rename {root => build/root}/etc/services.d/coredns/run (100%) rename {root => build/root}/etc/services.d/wireguard/run (100%) create mode 100644 dappnode_package.json create mode 100644 docker-compose.yml delete mode 100644 jenkins-vars.yml diff --git a/.gitignore b/.gitignore index 96374c4e..3a8e2f72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,43 +1,2 @@ -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk +# DAppNodeSDK release directories +build_* diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 7c668278..00000000 --- a/Jenkinsfile +++ /dev/null @@ -1,775 +0,0 @@ -pipeline { - agent { - label 'X86-64-MULTI' - } - options { - buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '60')) - parallelsAlwaysFailFast() - } - // Input to determine if this is a package check - parameters { - string(defaultValue: 'false', description: 'package check run', name: 'PACKAGE_CHECK') - } - // Configuration for the variables used for this specific repo - environment { - BUILDS_DISCORD=credentials('build_webhook_url') - GITHUB_TOKEN=credentials('498b4638-2d02-4ce5-832d-8a57d01d97ab') - GITLAB_TOKEN=credentials('b6f0f1dd-6952-4cf6-95d1-9c06380283f0') - GITLAB_NAMESPACE=credentials('gitlab-namespace-id') - CONTAINER_NAME = 'wireguard' - BUILD_VERSION_ARG = 'WIREGUARD_VERSION' - LS_USER = 'linuxserver' - LS_REPO = 'docker-wireguard' - DOCKERHUB_IMAGE = 'linuxserver/wireguard' - DEV_DOCKERHUB_IMAGE = 'lsiodev/wireguard' - PR_DOCKERHUB_IMAGE = 'lspipepr/wireguard' - DIST_IMAGE = 'ubuntu' - MULTIARCH='true' - CI='false' - CI_WEB='false' - CI_PORT='8080' - CI_SSL='false' - CI_DELAY='120' - CI_DOCKERENV='TZ=US/Pacific' - CI_AUTH='user:password' - CI_WEBPATH='' - } - stages { - // Setup all the basic environment variables needed for the build - stage("Set ENV Variables base"){ - steps{ - script{ - env.EXIT_STATUS = '' - env.LS_RELEASE = sh( - script: '''docker run --rm ghcr.io/linuxserver/alexeiled-skopeo sh -c 'skopeo inspect docker://docker.io/'${DOCKERHUB_IMAGE}':latest 2>/dev/null' | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''', - returnStdout: true).trim() - env.LS_RELEASE_NOTES = sh( - script: '''cat readme-vars.yml | awk -F \\" '/date: "[0-9][0-9].[0-9][0-9].[0-9][0-9]:/ {print $4;exit;}' | sed -E ':a;N;$!ba;s/\\r{0,1}\\n/\\\\n/g' ''', - returnStdout: true).trim() - env.GITHUB_DATE = sh( - script: '''date '+%Y-%m-%dT%H:%M:%S%:z' ''', - returnStdout: true).trim() - env.COMMIT_SHA = sh( - script: '''git rev-parse HEAD''', - returnStdout: true).trim() - env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/commit/' + env.GIT_COMMIT - env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DOCKERHUB_IMAGE + '/tags/' - env.PULL_REQUEST = env.CHANGE_ID - env.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.md ./.github/ISSUE_TEMPLATE/issue.feature.md ./.github/PULL_REQUEST_TEMPLATE.md ./.github/workflows/greetings.yml ./.github/workflows/stale.yml ./root/donate.txt ./.github/workflows/package_trigger.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/external_trigger.yml ./.github/workflows/external_trigger_scheduler.yml' - } - script{ - env.LS_RELEASE_NUMBER = sh( - script: '''echo ${LS_RELEASE} |sed 's/^.*-ls//g' ''', - returnStdout: true).trim() - } - script{ - env.LS_TAG_NUMBER = sh( - script: '''#! /bin/bash - tagsha=$(git rev-list -n 1 ${LS_RELEASE} 2>/dev/null) - if [ "${tagsha}" == "${COMMIT_SHA}" ]; then - echo ${LS_RELEASE_NUMBER} - elif [ -z "${GIT_COMMIT}" ]; then - echo ${LS_RELEASE_NUMBER} - else - echo $((${LS_RELEASE_NUMBER} + 1)) - fi''', - returnStdout: true).trim() - } - } - } - /* ####################### - Package Version Tagging - ####################### */ - // Grab the current package versions in Git to determine package tag - stage("Set Package tag"){ - steps{ - script{ - env.PACKAGE_TAG = sh( - script: '''#!/bin/bash - if [ -e package_versions.txt ] ; then - cat package_versions.txt | md5sum | cut -c1-8 - else - echo none - fi''', - returnStdout: true).trim() - } - } - } - /* ######################## - External Release Tagging - ######################## */ - // If this is a custom command to determine version use that command - stage("Set tag custom bash"){ - steps{ - script{ - env.EXT_RELEASE = sh( - script: ''' curl -sX GET https://api.github.com/repos/WireGuard/wireguard-tools/tags | jq -r .[0].name ''', - returnStdout: true).trim() - env.RELEASE_LINK = 'custom_command' - } - } - } - // Sanitize the release tag and strip illegal docker or github characters - stage("Sanitize tag"){ - steps{ - script{ - env.EXT_RELEASE_CLEAN = sh( - script: '''echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g' ''', - returnStdout: true).trim() - } - } - } - // If this is a master build use live docker endpoints - stage("Set ENV live build"){ - when { - branch "master" - environment name: 'CHANGE_ID', value: '' - } - steps { - script{ - env.IMAGE = env.DOCKERHUB_IMAGE - env.GITHUBIMAGE = 'ghcr.io/' + env.LS_USER + '/' + env.CONTAINER_NAME - env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/' + env.CONTAINER_NAME - if (env.MULTIARCH == 'true') { - env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + '|arm32v7-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER - } else { - env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER - } - env.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER - env.META_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER - env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN - } - } - } - // If this is a dev build use dev docker endpoints - stage("Set ENV dev build"){ - when { - not {branch "master"} - environment name: 'CHANGE_ID', value: '' - } - steps { - script{ - env.IMAGE = env.DEV_DOCKERHUB_IMAGE - env.GITHUBIMAGE = 'ghcr.io/' + env.LS_USER + '/lsiodev-' + env.CONTAINER_NAME - env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/lsiodev-' + env.CONTAINER_NAME - if (env.MULTIARCH == 'true') { - env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '|arm32v7-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA - } else { - env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA - } - env.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA - env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-dev-' + env.COMMIT_SHA - env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN - env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/' - } - } - } - // If this is a pull request build use dev docker endpoints - stage("Set ENV PR build"){ - when { - not {environment name: 'CHANGE_ID', value: ''} - } - steps { - script{ - env.IMAGE = env.PR_DOCKERHUB_IMAGE - env.GITHUBIMAGE = 'ghcr.io/' + env.LS_USER + '/lspipepr-' + env.CONTAINER_NAME - env.GITLABIMAGE = 'registry.gitlab.com/linuxserver.io/' + env.LS_REPO + '/lspipepr-' + env.CONTAINER_NAME - if (env.MULTIARCH == 'true') { - env.CI_TAGS = 'amd64-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + '|arm32v7-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST + '|arm64v8-' + env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST - } else { - env.CI_TAGS = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST - } - env.VERSION_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST - env.META_TAG = env.EXT_RELEASE_CLEAN + '-pkg-' + env.PACKAGE_TAG + '-pr-' + env.PULL_REQUEST - env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN - env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/pull/' + env.PULL_REQUEST - env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.PR_DOCKERHUB_IMAGE + '/tags/' - } - } - } - // Run ShellCheck - stage('ShellCheck') { - when { - environment name: 'CI', value: 'true' - } - steps { - withCredentials([ - string(credentialsId: 'ci-tests-s3-key-id', variable: 'S3_KEY'), - string(credentialsId: 'ci-tests-s3-secret-access-key', variable: 'S3_SECRET') - ]) { - script{ - env.SHELLCHECK_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/shellcheck-result.xml' - } - sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-shellcheck/master/checkrun.sh | /bin/bash''' - sh '''#! /bin/bash - set -e - docker pull ghcr.io/linuxserver/lsiodev-spaces-file-upload:latest - docker run --rm \ - -e DESTINATION=\"${IMAGE}/${META_TAG}/shellcheck-result.xml\" \ - -e FILE_NAME="shellcheck-result.xml" \ - -e MIMETYPE="text/xml" \ - -v ${WORKSPACE}:/mnt \ - -e SECRET_KEY=\"${S3_SECRET}\" \ - -e ACCESS_KEY=\"${S3_KEY}\" \ - -t ghcr.io/linuxserver/lsiodev-spaces-file-upload:latest \ - python /upload.py''' - } - } - } - // Use helper containers to render templated files - stage('Update-Templates') { - when { - branch "master" - environment name: 'CHANGE_ID', value: '' - expression { - env.CONTAINER_NAME != null - } - } - steps { - sh '''#! /bin/bash - set -e - TEMPDIR=$(mktemp -d) - docker pull ghcr.io/linuxserver/jenkins-builder:latest - docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH=master -v ${TEMPDIR}:/ansible/jenkins ghcr.io/linuxserver/jenkins-builder:latest - CURRENTHASH=$(grep -hs ^ ${TEMPLATED_FILES} | md5sum | cut -c1-8) - cd ${TEMPDIR}/docker-${CONTAINER_NAME} - NEWHASH=$(grep -hs ^ ${TEMPLATED_FILES} | md5sum | cut -c1-8) - if [[ "${CURRENTHASH}" != "${NEWHASH}" ]]; then - mkdir -p ${TEMPDIR}/repo - git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/repo/${LS_REPO} - cd ${TEMPDIR}/repo/${LS_REPO} - git checkout -f master - cd ${TEMPDIR}/docker-${CONTAINER_NAME} - mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github/workflows - mkdir -p ${TEMPDIR}/repo/${LS_REPO}/.github/ISSUE_TEMPLATE - rm -f ${TEMPDIR}/repo/${LS_REPO}/.github/ISSUE_TEMPLATE.md - cp --parents ${TEMPLATED_FILES} ${TEMPDIR}/repo/${LS_REPO}/ || : - cd ${TEMPDIR}/repo/${LS_REPO}/ - git add ${TEMPLATED_FILES} - git rm .github/ISSUE_TEMPLATE.md || : - git commit -m 'Bot Updating Templated Files' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all - echo "true" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} - else - echo "false" > /tmp/${COMMIT_SHA}-${BUILD_NUMBER} - fi - mkdir -p ${TEMPDIR}/gitbook - git clone https://github.com/linuxserver/docker-documentation.git ${TEMPDIR}/gitbook/docker-documentation - if [[ ("${BRANCH_NAME}" == "master") || ("${BRANCH_NAME}" == "main") ]] && [[ (! -f ${TEMPDIR}/gitbook/docker-documentation/images/docker-${CONTAINER_NAME}.md) || ("$(md5sum ${TEMPDIR}/gitbook/docker-documentation/images/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/docker-${CONTAINER_NAME}.md | awk '{ print $1 }')") ]]; then - cp ${TEMPDIR}/docker-${CONTAINER_NAME}/docker-${CONTAINER_NAME}.md ${TEMPDIR}/gitbook/docker-documentation/images/ - cd ${TEMPDIR}/gitbook/docker-documentation/ - git add images/docker-${CONTAINER_NAME}.md - git commit -m 'Bot Updating Documentation' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/docker-documentation.git --all - fi - mkdir -p ${TEMPDIR}/unraid - git clone https://github.com/linuxserver/docker-templates.git ${TEMPDIR}/unraid/docker-templates - git clone https://github.com/linuxserver/templates.git ${TEMPDIR}/unraid/templates - if [[ -f ${TEMPDIR}/unraid/docker-templates/linuxserver.io/img/${CONTAINER_NAME}-icon.png ]]; then - sed -i "s|master/linuxserver.io/img/linuxserver-ls-logo.png|master/linuxserver.io/img/${CONTAINER_NAME}-icon.png|" ${TEMPDIR}/docker-${CONTAINER_NAME}/${CONTAINER_NAME}.xml - fi - if [[ ("${BRANCH_NAME}" == "master") || ("${BRANCH_NAME}" == "main") ]] && [[ (! -f ${TEMPDIR}/unraid/templates/unraid/${CONTAINER_NAME}.xml) || ("$(md5sum ${TEMPDIR}/unraid/templates/unraid/${CONTAINER_NAME}.xml | awk '{ print $1 }')" != "$(md5sum ${TEMPDIR}/docker-${CONTAINER_NAME}/${CONTAINER_NAME}.xml | awk '{ print $1 }')") ]]; then - if grep -wq "${CONTAINER_NAME}" ${TEMPDIR}/unraid/templates/unraid/ignore.list; then - echo "Image is on the ignore list, skipping Unraid template upload" - else - cp ${TEMPDIR}/docker-${CONTAINER_NAME}/${CONTAINER_NAME}.xml ${TEMPDIR}/unraid/templates/unraid/ - cd ${TEMPDIR}/unraid/templates/ - git add unraid/${CONTAINER_NAME}.xml - git commit -m 'Bot Updating Unraid Template' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/linuxserver/templates.git --all - fi - fi - rm -Rf ${TEMPDIR}''' - script{ - env.FILES_UPDATED = sh( - script: '''cat /tmp/${COMMIT_SHA}-${BUILD_NUMBER}''', - returnStdout: true).trim() - } - } - } - // Exit the build if the Templated files were just updated - stage('Template-exit') { - when { - branch "master" - environment name: 'CHANGE_ID', value: '' - environment name: 'FILES_UPDATED', value: 'true' - expression { - env.CONTAINER_NAME != null - } - } - steps { - script{ - env.EXIT_STATUS = 'ABORTED' - } - } - } - /* ####################### - GitLab Mirroring - ####################### */ - // Ping into Gitlab to mirror this repo and have a registry endpoint - stage("GitLab Mirror"){ - when { - environment name: 'EXIT_STATUS', value: '' - } - steps{ - sh '''curl -H "Content-Type: application/json" -H "Private-Token: ${GITLAB_TOKEN}" -X POST https://gitlab.com/api/v4/projects \ - -d '{"namespace_id":'${GITLAB_NAMESPACE}',\ - "name":"'${LS_REPO}'", - "mirror":true,\ - "import_url":"https://github.com/linuxserver/'${LS_REPO}'.git",\ - "issues_access_level":"disabled",\ - "merge_requests_access_level":"disabled",\ - "repository_access_level":"enabled",\ - "visibility":"public"}' ''' - } - } - /* ############### - Build Container - ############### */ - // Build Docker container for push to LS Repo - stage('Build-Single') { - when { - environment name: 'MULTIARCH', value: 'false' - environment name: 'EXIT_STATUS', value: '' - } - steps { - echo "Running on node: ${NODE_NAME}" - sh "docker build --no-cache --pull -t ${IMAGE}:${META_TAG} \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - } - } - // Build MultiArch Docker containers for push to LS Repo - stage('Build-Multi') { - when { - environment name: 'MULTIARCH', value: 'true' - environment name: 'EXIT_STATUS', value: '' - } - parallel { - stage('Build X86') { - steps { - echo "Running on node: ${NODE_NAME}" - sh "docker build --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - } - } - stage('Build ARMHF') { - agent { - label 'ARMHF' - } - steps { - echo "Running on node: ${NODE_NAME}" - echo 'Logging into Github' - sh '''#! /bin/bash - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - ''' - sh "docker build --no-cache --pull -f Dockerfile.armhf -t ${IMAGE}:arm32v7-${META_TAG} \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - sh "docker tag ${IMAGE}:arm32v7-${META_TAG} ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER}" - retry(5) { - sh "docker push ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER}" - } - sh '''docker rmi \ - ${IMAGE}:arm32v7-${META_TAG} \ - ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} || :''' - } - } - stage('Build ARM64') { - agent { - label 'ARM64' - } - steps { - echo "Running on node: ${NODE_NAME}" - echo 'Logging into Github' - sh '''#! /bin/bash - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - ''' - sh "docker build --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." - sh "docker tag ${IMAGE}:arm64v8-${META_TAG} ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" - retry(5) { - sh "docker push ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}" - } - sh '''docker rmi \ - ${IMAGE}:arm64v8-${META_TAG} \ - ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || :''' - } - } - } - } - // Take the image we just built and dump package versions for comparison - stage('Update-packages') { - when { - branch "master" - environment name: 'CHANGE_ID', value: '' - environment name: 'EXIT_STATUS', value: '' - } - steps { - sh '''#! /bin/bash - set -e - TEMPDIR=$(mktemp -d) - if [ "${MULTIARCH}" == "true" ]; then - LOCAL_CONTAINER=${IMAGE}:amd64-${META_TAG} - else - LOCAL_CONTAINER=${IMAGE}:${META_TAG} - fi - if [ "${DIST_IMAGE}" == "alpine" ]; then - docker run --rm --entrypoint '/bin/sh' -v ${TEMPDIR}:/tmp ${LOCAL_CONTAINER} -c '\ - apk info -v > /tmp/package_versions.txt && \ - sort -o /tmp/package_versions.txt /tmp/package_versions.txt && \ - chmod 777 /tmp/package_versions.txt' - elif [ "${DIST_IMAGE}" == "ubuntu" ]; then - docker run --rm --entrypoint '/bin/sh' -v ${TEMPDIR}:/tmp ${LOCAL_CONTAINER} -c '\ - apt list -qq --installed | sed "s#/.*now ##g" | cut -d" " -f1 > /tmp/package_versions.txt && \ - sort -o /tmp/package_versions.txt /tmp/package_versions.txt && \ - chmod 777 /tmp/package_versions.txt' - fi - NEW_PACKAGE_TAG=$(md5sum ${TEMPDIR}/package_versions.txt | cut -c1-8 ) - echo "Package tag sha from current packages in buit container is ${NEW_PACKAGE_TAG} comparing to old ${PACKAGE_TAG} from github" - if [ "${NEW_PACKAGE_TAG}" != "${PACKAGE_TAG}" ]; then - git clone https://github.com/${LS_USER}/${LS_REPO}.git ${TEMPDIR}/${LS_REPO} - git --git-dir ${TEMPDIR}/${LS_REPO}/.git checkout -f master - cp ${TEMPDIR}/package_versions.txt ${TEMPDIR}/${LS_REPO}/ - cd ${TEMPDIR}/${LS_REPO}/ - wait - git add package_versions.txt - git commit -m 'Bot Updating Package Versions' - git push https://LinuxServer-CI:${GITHUB_TOKEN}@github.com/${LS_USER}/${LS_REPO}.git --all - echo "true" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} - echo "Package tag updated, stopping build process" - else - echo "false" > /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER} - echo "Package tag is same as previous continue with build process" - fi - rm -Rf ${TEMPDIR}''' - script{ - env.PACKAGE_UPDATED = sh( - script: '''cat /tmp/packages-${COMMIT_SHA}-${BUILD_NUMBER}''', - returnStdout: true).trim() - } - } - } - // Exit the build if the package file was just updated - stage('PACKAGE-exit') { - when { - branch "master" - environment name: 'CHANGE_ID', value: '' - environment name: 'PACKAGE_UPDATED', value: 'true' - environment name: 'EXIT_STATUS', value: '' - } - steps { - sh '''#! /bin/bash - echo "Packages were updated. Cleaning up the image and exiting." - if [ "${MULTIARCH}" == "true" ]; then - docker rmi ${IMAGE}:amd64-${META_TAG} - else - docker rmi ${IMAGE}:${META_TAG} - fi''' - script{ - env.EXIT_STATUS = 'ABORTED' - } - } - } - // Exit the build if this is just a package check and there are no changes to push - stage('PACKAGECHECK-exit') { - when { - branch "master" - environment name: 'CHANGE_ID', value: '' - environment name: 'PACKAGE_UPDATED', value: 'false' - environment name: 'EXIT_STATUS', value: '' - expression { - params.PACKAGE_CHECK == 'true' - } - } - steps { - sh '''#! /bin/bash - echo "There are no package updates. Cleaning up the image and exiting." - if [ "${MULTIARCH}" == "true" ]; then - docker rmi ${IMAGE}:amd64-${META_TAG} - else - docker rmi ${IMAGE}:${META_TAG} - fi''' - script{ - env.EXIT_STATUS = 'ABORTED' - } - } - } - /* ####### - Testing - ####### */ - // Run Container tests - stage('Test') { - when { - environment name: 'CI', value: 'true' - environment name: 'EXIT_STATUS', value: '' - } - steps { - withCredentials([ - string(credentialsId: 'ci-tests-s3-key-id', variable: 'S3_KEY'), - string(credentialsId: 'ci-tests-s3-secret-access-key ', variable: 'S3_SECRET') - ]) { - script{ - env.CI_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/index.html' - } - sh '''#! /bin/bash - set -e - docker pull ghcr.io/linuxserver/lsiodev-ci:latest - if [ "${MULTIARCH}" == "true" ]; then - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm32v7-${META_TAG} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} - fi - docker run --rm \ - --shm-size=1gb \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -e IMAGE=\"${IMAGE}\" \ - -e DELAY_START=\"${CI_DELAY}\" \ - -e TAGS=\"${CI_TAGS}\" \ - -e META_TAG=\"${META_TAG}\" \ - -e PORT=\"${CI_PORT}\" \ - -e SSL=\"${CI_SSL}\" \ - -e BASE=\"${DIST_IMAGE}\" \ - -e SECRET_KEY=\"${S3_SECRET}\" \ - -e ACCESS_KEY=\"${S3_KEY}\" \ - -e DOCKER_ENV=\"${CI_DOCKERENV}\" \ - -e WEB_SCREENSHOT=\"${CI_WEB}\" \ - -e WEB_AUTH=\"${CI_AUTH}\" \ - -e WEB_PATH=\"${CI_WEBPATH}\" \ - -e DO_REGION="ams3" \ - -e DO_BUCKET="lsio-ci" \ - -t ghcr.io/linuxserver/lsiodev-ci:latest \ - python /ci/ci.py''' - } - } - } - /* ################## - Release Logic - ################## */ - // If this is an amd64 only image only push a single image - stage('Docker-Push-Single') { - when { - environment name: 'MULTIARCH', value: 'false' - environment name: 'EXIT_STATUS', value: '' - } - steps { - withCredentials([ - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', - usernameVariable: 'DOCKERUSER', - passwordVariable: 'DOCKERPASS' - ] - ]) { - retry(5) { - sh '''#! /bin/bash - set -e - echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin - for PUSHIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${IMAGE}"; do - docker tag ${IMAGE}:${META_TAG} ${PUSHIMAGE}:${META_TAG} - docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:latest - docker tag ${PUSHIMAGE}:${META_TAG} ${PUSHIMAGE}:${EXT_RELEASE_TAG} - docker push ${PUSHIMAGE}:latest - docker push ${PUSHIMAGE}:${META_TAG} - docker push ${PUSHIMAGE}:${EXT_RELEASE_TAG} - done - ''' - } - sh '''#! /bin/bash - for DELETEIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${IMAGE}"; do - docker rmi \ - ${DELETEIMAGE}:${META_TAG} \ - ${DELETEIMAGE}:${EXT_RELEASE_TAG} \ - ${DELETEIMAGE}:latest || : - done - ''' - } - } - } - // If this is a multi arch release push all images and define the manifest - stage('Docker-Push-Multi') { - when { - environment name: 'MULTIARCH', value: 'true' - environment name: 'EXIT_STATUS', value: '' - } - steps { - withCredentials([ - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', - usernameVariable: 'DOCKERUSER', - passwordVariable: 'DOCKERPASS' - ] - ]) { - retry(5) { - sh '''#! /bin/bash - set -e - echo $DOCKERPASS | docker login -u $DOCKERUSER --password-stdin - echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin - echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin - if [ "${CI}" == "false" ]; then - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm32v7-${META_TAG} - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} - fi - for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}"; do - docker tag ${IMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} - docker tag ${IMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${META_TAG} - docker tag ${IMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} - docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-latest - docker tag ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-latest - docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-latest - docker tag ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} - docker tag ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} - docker tag ${MANIFESTIMAGE}:arm64v8-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} - docker push ${MANIFESTIMAGE}:amd64-${META_TAG} - docker push ${MANIFESTIMAGE}:arm32v7-${META_TAG} - docker push ${MANIFESTIMAGE}:arm64v8-${META_TAG} - docker push ${MANIFESTIMAGE}:amd64-latest - docker push ${MANIFESTIMAGE}:arm32v7-latest - docker push ${MANIFESTIMAGE}:arm64v8-latest - docker push ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} - docker push ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} - docker push ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} - docker manifest push --purge ${MANIFESTIMAGE}:latest || : - docker manifest create ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm32v7-latest ${MANIFESTIMAGE}:arm64v8-latest - docker manifest annotate ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:arm32v7-latest --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:arm64v8-latest --os linux --arch arm64 --variant v8 - docker manifest push --purge ${MANIFESTIMAGE}:${META_TAG} || : - docker manifest create ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm32v7-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} - docker manifest annotate ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:arm32v7-${META_TAG} --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} --os linux --arch arm64 --variant v8 - docker manifest push --purge ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} || : - docker manifest create ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} - docker manifest annotate ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm32v7-${EXT_RELEASE_TAG} --os linux --arch arm - docker manifest annotate ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} --os linux --arch arm64 --variant v8 - docker manifest push --purge ${MANIFESTIMAGE}:latest - docker manifest push --purge ${MANIFESTIMAGE}:${META_TAG} - docker manifest push --purge ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} - done - ''' - } - sh '''#! /bin/bash - for DELETEIMAGE in "${GITHUBIMAGE}" "${GITLABIMAGE}" "${IMAGE}"; do - docker rmi \ - ${DELETEIMAGE}:amd64-${META_TAG} \ - ${DELETEIMAGE}:amd64-latest \ - ${DELETEIMAGE}:amd64-${EXT_RELEASE_TAG} \ - ${DELETEIMAGE}:arm32v7-${META_TAG} \ - ${DELETEIMAGE}:arm32v7-latest \ - ${DELETEIMAGE}:arm32v7-${EXT_RELEASE_TAG} \ - ${DELETEIMAGE}:arm64v8-${META_TAG} \ - ${DELETEIMAGE}:arm64v8-latest \ - ${DELETEIMAGE}:arm64v8-${EXT_RELEASE_TAG} || : - done - docker rmi \ - ghcr.io/linuxserver/lsiodev-buildcache:arm32v7-${COMMIT_SHA}-${BUILD_NUMBER} \ - ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || : - ''' - } - } - } - // If this is a public release tag it in the LS Github - stage('Github-Tag-Push-Release') { - when { - branch "master" - expression { - env.LS_RELEASE != env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER - } - environment name: 'CHANGE_ID', value: '' - environment name: 'EXIT_STATUS', value: '' - } - steps { - echo "Pushing New tag for current commit ${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" - sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \ - -d '{"tag":"'${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}'",\ - "object": "'${COMMIT_SHA}'",\ - "message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to master",\ - "type": "commit",\ - "tagger": {"name": "LinuxServer Jenkins","email": "jenkins@linuxserver.io","date": "'${GITHUB_DATE}'"}}' ''' - echo "Pushing New release for Tag" - sh '''#! /bin/bash - echo "Updating to ${EXT_RELEASE_CLEAN}" > releasebody.json - echo '{"tag_name":"'${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}'",\ - "target_commitish": "master",\ - "name": "'${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}'",\ - "body": "**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n**Remote Changes:**\\n\\n' > start - printf '","draft": false,"prerelease": false}' >> releasebody.json - paste -d'\\0' start releasebody.json > releasebody.json.done - curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done''' - } - } - // Use helper container to sync the current README on master to the dockerhub endpoint - stage('Sync-README') { - when { - environment name: 'CHANGE_ID', value: '' - environment name: 'EXIT_STATUS', value: '' - } - steps { - withCredentials([ - [ - $class: 'UsernamePasswordMultiBinding', - credentialsId: '3f9ba4d5-100d-45b0-a3c4-633fd6061207', - usernameVariable: 'DOCKERUSER', - passwordVariable: 'DOCKERPASS' - ] - ]) { - sh '''#! /bin/bash - set -e - TEMPDIR=$(mktemp -d) - docker pull ghcr.io/linuxserver/jenkins-builder:latest - docker run --rm -e CONTAINER_NAME=${CONTAINER_NAME} -e GITHUB_BRANCH="${BRANCH_NAME}" -v ${TEMPDIR}:/ansible/jenkins ghcr.io/linuxserver/jenkins-builder:latest - docker pull ghcr.io/linuxserver/lsiodev-readme-sync - docker run --rm=true \ - -e DOCKERHUB_USERNAME=$DOCKERUSER \ - -e DOCKERHUB_PASSWORD=$DOCKERPASS \ - -e GIT_REPOSITORY=${LS_USER}/${LS_REPO} \ - -e DOCKER_REPOSITORY=${IMAGE} \ - -e GIT_BRANCH=master \ - -v ${TEMPDIR}/docker-${CONTAINER_NAME}:/mnt \ - ghcr.io/linuxserver/lsiodev-readme-sync bash -c 'node sync' - rm -Rf ${TEMPDIR} ''' - } - } - } - // If this is a Pull request send the CI link as a comment on it - stage('Pull Request Comment') { - when { - not {environment name: 'CHANGE_ID', value: ''} - environment name: 'CI', value: 'true' - environment name: 'EXIT_STATUS', value: '' - } - steps { - sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/issues/${PULL_REQUEST}/comments \ - -d '{"body": "I am a bot, here are the test results for this PR: \\n'${CI_URL}' \\n'${SHELLCHECK_URL}'"}' ''' - } - } - } - /* ###################### - Send status to Discord - ###################### */ - post { - always { - script{ - if (env.EXIT_STATUS == "ABORTED"){ - sh 'echo "build aborted"' - } - else if (currentBuild.currentResult == "SUCCESS"){ - sh ''' curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png","embeds": [{"color": 1681177,\ - "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** Success\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ - "username": "Jenkins"}' ${BUILDS_DISCORD} ''' - } - else { - sh ''' curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png","embeds": [{"color": 16711680,\ - "description": "**Build:** '${BUILD_NUMBER}'\\n**CI Results:** '${CI_URL}'\\n**ShellCheck Results:** '${SHELLCHECK_URL}'\\n**Status:** failure\\n**Job:** '${RUN_DISPLAY_URL}'\\n**Change:** '${CODE_URL}'\\n**External Release:**: '${RELEASE_LINK}'\\n**DockerHub:** '${DOCKERHUB_LINK}'\\n"}],\ - "username": "Jenkins"}' ${BUILDS_DISCORD} ''' - } - } - } - cleanup { - cleanWs() - } - } -} diff --git a/avatar-default.png b/avatar-default.png new file mode 100644 index 0000000000000000000000000000000000000000..ee2ac7328b3f6354ce179bc75bb571279d9ce411 GIT binary patch literal 3377 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 literal 0 HcmV?d00001 diff --git a/.dockerignore b/build/.dockerignore similarity index 65% rename from .dockerignore rename to build/.dockerignore index cdb1a82f..26260e27 100644 --- a/.dockerignore +++ b/build/.dockerignore @@ -4,3 +4,5 @@ .gitattributes READMETEMPLATE.md README.md +root/app/node_modules +root/app/dist diff --git a/.gitattributes b/build/.gitattributes similarity index 100% rename from .gitattributes rename to build/.gitattributes diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 00000000..77affc59 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,45 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +# DAppNodeSDK release directories +build_* diff --git a/Dockerfile b/build/Dockerfile similarity index 93% rename from Dockerfile rename to build/Dockerfile index c0ee38c9..23d87952 100644 --- a/Dockerfile +++ b/build/Dockerfile @@ -30,7 +30,9 @@ RUN \ openresolv \ perl \ pkg-config \ - qrencode && \ + qrencode \ + nodejs \ + npm && \ echo "**** install wireguard-tools ****" && \ if [ -z ${WIREGUARD_RELEASE+x} ]; then \ WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ @@ -60,6 +62,9 @@ RUN \ # add local files COPY /root / +RUN npm i -g npm@latest +RUN npm install --prefix=/app/ +RUN npm run build --prefix=/app/ # ports and volumes EXPOSE 51820/udp diff --git a/Dockerfile.aarch64 b/build/Dockerfile.aarch64 similarity index 100% rename from Dockerfile.aarch64 rename to build/Dockerfile.aarch64 diff --git a/Dockerfile.armhf b/build/Dockerfile.armhf similarity index 100% rename from Dockerfile.armhf rename to build/Dockerfile.armhf diff --git a/LICENSE b/build/LICENSE similarity index 100% rename from LICENSE rename to build/LICENSE diff --git a/README.md b/build/README.md similarity index 100% rename from README.md rename to build/README.md diff --git a/package_versions.txt b/build/package_versions.txt similarity index 100% rename from package_versions.txt rename to build/package_versions.txt diff --git a/readme-vars.yml b/build/readme-vars.yml similarity index 100% rename from readme-vars.yml rename to build/readme-vars.yml diff --git a/build/root/app/.gitignore b/build/root/app/.gitignore new file mode 100644 index 00000000..04c01ba7 --- /dev/null +++ b/build/root/app/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ \ No newline at end of file diff --git a/root/app/add-peer b/build/root/app/add-peer similarity index 100% rename from root/app/add-peer rename to build/root/app/add-peer diff --git a/build/root/app/package-lock.json b/build/root/app/package-lock.json new file mode 100644 index 00000000..dc6deb43 --- /dev/null +++ b/build/root/app/package-lock.json @@ -0,0 +1,1913 @@ +{ + "name": "wireguard-http", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@eslint/eslintrc": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", + "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bunyan": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.6.tgz", + "integrity": "sha512-YiozPOOsS6bIuz31ilYqR5SlLif4TBWsousN2aCWLi5233nZSX19tFbcQUPdR7xJ8ypPyxkCGNxg0CIV5n9qxQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cors": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz", + "integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg==", + "dev": true + }, + "@types/express": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz", + "integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz", + "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "@types/mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", + "dev": true + }, + "@types/node": { + "version": "14.14.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.21.tgz", + "integrity": "sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A==", + "dev": true + }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.8.tgz", + "integrity": "sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA==", + "dev": true, + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz", + "integrity": "sha512-ygqDUm+BUPvrr0jrXqoteMqmIaZ/bixYOc3A4BRwzEPTZPi6E+n44rzNZWaB0YvtukgP+aoj0i/fyx7FkM2p1w==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.13.0", + "@typescript-eslint/scope-manager": "4.13.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "tsutils": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.1.tgz", + "integrity": "sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.13.0.tgz", + "integrity": "sha512-/ZsuWmqagOzNkx30VWYV3MNB/Re/CGv/7EzlqZo5RegBN8tMuPaBgNK6vPBCQA8tcYrbsrTdbx3ixMRRKEEGVw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.13.0", + "@typescript-eslint/types": "4.13.0", + "@typescript-eslint/typescript-estree": "4.13.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.13.0.tgz", + "integrity": "sha512-KO0J5SRF08pMXzq9+abyHnaGQgUJZ3Z3ax+pmqz9vl81JxmTTOUfQmq7/4awVfq09b6C4owNlOgOwp61pYRBSg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.13.0", + "@typescript-eslint/types": "4.13.0", + "@typescript-eslint/typescript-estree": "4.13.0", + "debug": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.13.0.tgz", + "integrity": "sha512-UpK7YLG2JlTp/9G4CHe7GxOwd93RBf3aHO5L+pfjIrhtBvZjHKbMhBXTIQNkbz7HZ9XOe++yKrXutYm5KmjWgQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.13.0", + "@typescript-eslint/visitor-keys": "4.13.0" + } + }, + "@typescript-eslint/types": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.13.0.tgz", + "integrity": "sha512-/+aPaq163oX+ObOG00M0t9tKkOgdv9lq0IQv/y4SqGkAXmhFmCfgsELV7kOCTb2vVU5VOmVwXBXJTDr353C1rQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.13.0.tgz", + "integrity": "sha512-9A0/DFZZLlGXn5XA349dWQFwPZxcyYyCFX5X88nWs2uachRDwGeyPz46oTsm9ZJE66EALvEns1lvBwa4d9QxMg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.13.0", + "@typescript-eslint/visitor-keys": "4.13.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "tsutils": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.1.tgz", + "integrity": "sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.13.0.tgz", + "integrity": "sha512-6RoxWK05PAibukE7jElqAtNMq+RWZyqJ6Q/GdIxaiUj2Ept8jh8+FUVlbq9WxMYxkmEOPvCE5cRSyupMpwW31g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.13.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "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" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "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=" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "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" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "bunyan": { + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", + "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", + "requires": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "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=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "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" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "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=" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dtrace-provider": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", + "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", + "optional": true, + "requires": { + "nan": "^2.14.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "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==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "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=", + "dev": true + }, + "eslint": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz", + "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "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" + } + }, + "express-validator": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", + "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", + "requires": { + "lodash": "^4.17.20", + "validator": "^13.5.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", + "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", + "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "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" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", + "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", + "dev": true + }, + "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.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "optional": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "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" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "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==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^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=" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "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.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + }, + "mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "requires": { + "mime-db": "1.45.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "optional": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "optional": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "optional": true, + "requires": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "dependencies": { + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "optional": true, + "requires": { + "glob": "^6.0.1" + } + } + } + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "optional": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "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" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "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=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "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" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "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" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "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==" + }, + "safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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": { + "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": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "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==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", + "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", + "dev": true, + "requires": { + "ajv": "^7.0.2", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ajv": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", + "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "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.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tslint-microsoft-contrib": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz", + "integrity": "sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==", + "dev": true, + "requires": { + "tsutils": "^2.27.2 <2.29.0" + } + }, + "tslint-sonarts": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslint-sonarts/-/tslint-sonarts-1.9.0.tgz", + "integrity": "sha512-CJWt+IiYI8qggb2O/JPkS6CkC5DY1IcqRsm9EHJ+AxoWK70lvtP7jguochyNDMP2vIz/giGdWCfEM39x/I/Vnw==", + "dev": true, + "requires": { + "immutable": "^3.8.2" + } + }, + "tsutils": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz", + "integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "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" + } + }, + "typescript": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", + "dev": true + }, + "typestrict": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typestrict/-/typestrict-1.0.2.tgz", + "integrity": "sha512-4wEr84NPc0ldINrgwgSBTmbWPiGVbwO3c9xumM0ujp0DlzhTs3jUT0NtVBOd5UXneSXcStNJWj80zerbW2YR6Q==", + "dev": true, + "requires": { + "tslint-microsoft-contrib": "^5.0.3", + "tslint-sonarts": "^1.8.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/build/root/app/package.json b/build/root/app/package.json new file mode 100644 index 00000000..88d0c8d9 --- /dev/null +++ b/build/root/app/package.json @@ -0,0 +1,33 @@ +{ + "name": "wireguard-http", + "version": "0.1.0", + "description": "", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "rimraf ./dist", + "build": "npm run clean && tsc", + "start": "node ./dist/server.js", + "lint": "eslint . --ext .ts" + }, + "author": "lg@shardlabs.io", + "license": "MIT", + "dependencies": { + "bunyan": "^1.8.15", + "cors": "^2.8.5", + "express": "^4.17.1", + "express-validator": "^6.9.2" + }, + "devDependencies": { + "@types/bunyan": "^1.8.6", + "@types/cors": "2.8.9", + "@types/express": "^4.17.11", + "@types/node": "^14.14.21", + "@typescript-eslint/eslint-plugin": "^4.6.1", + "@typescript-eslint/parser": "^4.6.1", + "rimraf": "^3.0.2", + "eslint": "^7.13.0", + "typestrict": "^1.0.2", + "typescript": "4.1.3" + } +} diff --git a/root/app/show-peer b/build/root/app/show-peer similarity index 100% rename from root/app/show-peer rename to build/root/app/show-peer diff --git a/build/root/app/src/server.ts b/build/root/app/src/server.ts new file mode 100644 index 00000000..5bf848ff --- /dev/null +++ b/build/root/app/src/server.ts @@ -0,0 +1,49 @@ +import express from 'express'; +import { param, validationResult } from 'express-validator'; +import cors from 'cors'; +import path from 'path'; +import Logger from 'bunyan'; + +const app = express(); + +const port = process.env.SERVER_PORT || 80; +const dataDir: string = process.env.DATA_DIR || "/config"; +app.use(cors()) + +let silent; +const log = Logger.createLogger({ + name: "Server", + streams: [{ + stream: process.stdout, + level: silent ? 'fatal' : 30 + }] + }); + + +app.get('/:mode/:device', + [ + param('mode').isIn(['conf', 'qr']) + ], + (req: express.Request, res: express.Response) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + + let ext = 'conf'; + + if (req.params.mode === 'qr') ext = 'png'; + + const device: string = req.params.device; + + try { + res.status(200).sendFile(path.join(dataDir, `peer_${device}/peer_${device}.${ext}`)); + } catch(error: any){ + res.status(404).end('Not found'); + } + }); + + +app.listen(port, () => log.info({loc: '[LISTEN]'}, `Injector listening on port ${port}!`)) + +export default app; diff --git a/build/root/app/tsconfig.json b/build/root/app/tsconfig.json new file mode 100644 index 00000000..bc81cc0b --- /dev/null +++ b/build/root/app/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "allowJs": true, + "target": "es5", + "sourceMap": true, + "esModuleInterop": true, + "strict": true, + "outDir": "dist" + }, + "include": ["./src"] + } + \ No newline at end of file diff --git a/build/root/app/tslint.json b/build/root/app/tslint.json new file mode 100644 index 00000000..816e57c0 --- /dev/null +++ b/build/root/app/tslint.json @@ -0,0 +1,13 @@ +{ + "extends": "typestrict", + "rules": { + "no-debugger": true, + "mocha-avoid-only": true, + "prefer-const": true, + "no-var-keyword": true, + "no-commented-code": { + "severity": "warning" + }, + "no-use-before-declare": false + } +} \ No newline at end of file diff --git a/root/defaults/Corefile b/build/root/defaults/Corefile similarity index 100% rename from root/defaults/Corefile rename to build/root/defaults/Corefile diff --git a/root/defaults/peer.conf b/build/root/defaults/peer.conf similarity index 100% rename from root/defaults/peer.conf rename to build/root/defaults/peer.conf diff --git a/root/defaults/server.conf b/build/root/defaults/server.conf similarity index 100% rename from root/defaults/server.conf rename to build/root/defaults/server.conf diff --git a/root/donate.txt b/build/root/donate.txt similarity index 100% rename from root/donate.txt rename to build/root/donate.txt diff --git a/root/etc/cont-init.d/30-config b/build/root/etc/cont-init.d/30-config similarity index 100% rename from root/etc/cont-init.d/30-config rename to build/root/etc/cont-init.d/30-config diff --git a/root/etc/services.d/coredns/run b/build/root/etc/services.d/coredns/run similarity index 100% rename from root/etc/services.d/coredns/run rename to build/root/etc/services.d/coredns/run diff --git a/root/etc/services.d/wireguard/run b/build/root/etc/services.d/wireguard/run similarity index 100% rename from root/etc/services.d/wireguard/run rename to build/root/etc/services.d/wireguard/run diff --git a/dappnode_package.json b/dappnode_package.json new file mode 100644 index 00000000..07139516 --- /dev/null +++ b/dappnode_package.json @@ -0,0 +1,12 @@ +{ + "name": "wireguard.public.dappnode.eth", + "version": "0.1.0", + "description": "Wireguard for DAppNode", + "type": "service", + "author": "Shardlabs", + "categories": ["Developer tools"], + "links": { + "homepage": "https://your-project-homepage-or-docs.io" + }, + "license": "GLP-3.0" +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..20c5a723 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +version: "3.4" +services: + wireguard.public.dappnode.eth: + build: ./build + image: "wireguard.public.dappnode.eth:0.1.0" + restart: always + cap_add: + - NET_ADMIN + - SYS_MODULE + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Zagreb + - SERVERPORT=51820 + - PEERS= + - PEERDNS=172.33.1.2 + - SERVERURL=dappnode.shardlabs.io + - INTERNAL_SUBNET=172.33.10.0 + - ALLOWEDIPS=172.33.0.0/16 + volumes: + - /path/to/appdata/config:/config + - /lib/modules:/lib/modules + ports: + - 51820:51820/udp + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 \ No newline at end of file diff --git a/jenkins-vars.yml b/jenkins-vars.yml deleted file mode 100644 index 1b241b7f..00000000 --- a/jenkins-vars.yml +++ /dev/null @@ -1,29 +0,0 @@ ---- - -# jenkins variables -project_name: docker-wireguard -external_type: na -custom_version_command: "curl -sX GET https://api.github.com/repos/WireGuard/wireguard-tools/tags | jq -r .[0].name" -release_type: stable -release_tag: latest -ls_branch: master -repo_vars: - - CONTAINER_NAME = 'wireguard' - - BUILD_VERSION_ARG = 'WIREGUARD_VERSION' - - LS_USER = 'linuxserver' - - LS_REPO = 'docker-wireguard' - - DOCKERHUB_IMAGE = 'linuxserver/wireguard' - - DEV_DOCKERHUB_IMAGE = 'lsiodev/wireguard' - - PR_DOCKERHUB_IMAGE = 'lspipepr/wireguard' - - DIST_IMAGE = 'ubuntu' - - MULTIARCH='true' - - CI='false' - - CI_WEB='false' - - CI_PORT='8080' - - CI_SSL='false' - - CI_DELAY='120' - - CI_DOCKERENV='TZ=US/Pacific' - - CI_AUTH='user:password' - - CI_WEBPATH='' -sponsor_links: - - { name: "WireGuard", url: "https://www.wireguard.com/donations/" } \ No newline at end of file From 818d358399a494fa9a40bad912cfc5cfa549ed8c Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 21 Jan 2021 10:59:00 +0000 Subject: [PATCH 02/57] Added dappnode domain --- dappnode_package.json | 3 +++ docker-compose.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dappnode_package.json b/dappnode_package.json index 07139516..36af938c 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -5,6 +5,9 @@ "type": "service", "author": "Shardlabs", "categories": ["Developer tools"], + "globalEnvs": { + "all": true + }, "links": { "homepage": "https://your-project-homepage-or-docs.io" }, diff --git a/docker-compose.yml b/docker-compose.yml index 20c5a723..79219d26 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,7 @@ services: - SERVERPORT=51820 - PEERS= - PEERDNS=172.33.1.2 - - SERVERURL=dappnode.shardlabs.io + - SERVERURL=${_DAPPNODE_GLOBAL_HOSTNAME} - INTERNAL_SUBNET=172.33.10.0 - ALLOWEDIPS=172.33.0.0/16 volumes: From 01df2267e53f5acfb614423a06868c27ad4abd6b Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 21 Jan 2021 11:01:36 +0000 Subject: [PATCH 03/57] Changed config volume --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 79219d26..dbf88471 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,7 @@ services: - INTERNAL_SUBNET=172.33.10.0 - ALLOWEDIPS=172.33.0.0/16 volumes: - - /path/to/appdata/config:/config + - config:/config - /lib/modules:/lib/modules ports: - 51820:51820/udp From 1d3f3ce1cf81c382fdae45762a03b065c25de0f2 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 21 Jan 2021 12:13:04 +0100 Subject: [PATCH 04/57] Fixes --- build/root/etc/services.d/nodejs-web/run | 3 +++ docker-compose.yml | 18 +++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 build/root/etc/services.d/nodejs-web/run diff --git a/build/root/etc/services.d/nodejs-web/run b/build/root/etc/services.d/nodejs-web/run new file mode 100644 index 00000000..c229d8b9 --- /dev/null +++ b/build/root/etc/services.d/nodejs-web/run @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv bash + +npm start --prefix /app/ \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index dbf88471..6ddfd674 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,16 +11,16 @@ services: - PUID=1000 - PGID=1000 - TZ=Europe/Zagreb - - SERVERPORT=51820 + - SERVERPORT=51820 - PEERS= - - PEERDNS=172.33.1.2 - - SERVERURL=${_DAPPNODE_GLOBAL_HOSTNAME} - - INTERNAL_SUBNET=172.33.10.0 - - ALLOWEDIPS=172.33.0.0/16 + - PEERDNS=172.33.1.2 + - "SERVERURL=${_DAPPNODE_GLOBAL_HOSTNAME}" + - INTERNAL_SUBNET=172.33.10.0 + - ALLOWEDIPS=172.33.0.0/16 volumes: - - config:/config - - /lib/modules:/lib/modules + - "/path/to/appdata/config:/config" + - "/lib/modules:/lib/modules" ports: - - 51820:51820/udp + - "51820:51820/udp" sysctls: - - net.ipv4.conf.all.src_valid_mark=1 \ No newline at end of file + - net.ipv4.conf.all.src_valid_mark=1 From dc3fb6b96b4097e71f82cd489dda03070c229ed3 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 21 Jan 2021 13:48:12 +0100 Subject: [PATCH 05/57] Adding wizard --- dappnode_package.json | 5 +---- docker-compose.yml | 6 ++++-- setup-wizard.yml | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 setup-wizard.yml diff --git a/dappnode_package.json b/dappnode_package.json index 36af938c..f5fa6549 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -5,11 +5,8 @@ "type": "service", "author": "Shardlabs", "categories": ["Developer tools"], - "globalEnvs": { - "all": true - }, "links": { - "homepage": "https://your-project-homepage-or-docs.io" + "homepage": "https://github.com/Shard-Labs/docker-wireguard" }, "license": "GLP-3.0" } diff --git a/docker-compose.yml b/docker-compose.yml index 6ddfd674..bce1a41e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,13 +14,15 @@ services: - SERVERPORT=51820 - PEERS= - PEERDNS=172.33.1.2 - - "SERVERURL=${_DAPPNODE_GLOBAL_HOSTNAME}" + - SERVERURL= - INTERNAL_SUBNET=172.33.10.0 - ALLOWEDIPS=172.33.0.0/16 volumes: - - "/path/to/appdata/config:/config" + - "wg-config:/config" - "/lib/modules:/lib/modules" ports: - "51820:51820/udp" sysctls: - net.ipv4.conf.all.src_valid_mark=1 +volumes: + wg-config: {} diff --git a/setup-wizard.yml b/setup-wizard.yml new file mode 100644 index 00000000..c96087f8 --- /dev/null +++ b/setup-wizard.yml @@ -0,0 +1,20 @@ +version: "2" +fields: + - id: peers + target: + type: environment + name: PEERS + service: wireguard + title: Devices + description: >- + Please enter your names of your devices separated by commas and without whitespaces + required: true + + - id: domain + target: + type: environment + name: SERVERURL + service: node + title: Dappnode domain + description: >- + Dappnode domain name you would like to use (*.dyndns.dappnode.io domains are recommended). \ No newline at end of file From 5c602b2b5485aa6bdaffcd1ee399d2a43b943de0 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 21 Jan 2021 10:59:00 +0000 Subject: [PATCH 06/57] Added dappnode domain Changed config volume Fixes Adding wizard --- build/root/etc/services.d/nodejs-web/run | 3 +++ dappnode_package.json | 2 +- docker-compose.yml | 20 +++++++++++--------- setup-wizard.yml | 20 ++++++++++++++++++++ 4 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 build/root/etc/services.d/nodejs-web/run create mode 100644 setup-wizard.yml diff --git a/build/root/etc/services.d/nodejs-web/run b/build/root/etc/services.d/nodejs-web/run new file mode 100644 index 00000000..c229d8b9 --- /dev/null +++ b/build/root/etc/services.d/nodejs-web/run @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv bash + +npm start --prefix /app/ \ No newline at end of file diff --git a/dappnode_package.json b/dappnode_package.json index 07139516..f5fa6549 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -6,7 +6,7 @@ "author": "Shardlabs", "categories": ["Developer tools"], "links": { - "homepage": "https://your-project-homepage-or-docs.io" + "homepage": "https://github.com/Shard-Labs/docker-wireguard" }, "license": "GLP-3.0" } diff --git a/docker-compose.yml b/docker-compose.yml index 20c5a723..bce1a41e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,16 +11,18 @@ services: - PUID=1000 - PGID=1000 - TZ=Europe/Zagreb - - SERVERPORT=51820 + - SERVERPORT=51820 - PEERS= - - PEERDNS=172.33.1.2 - - SERVERURL=dappnode.shardlabs.io - - INTERNAL_SUBNET=172.33.10.0 - - ALLOWEDIPS=172.33.0.0/16 + - PEERDNS=172.33.1.2 + - SERVERURL= + - INTERNAL_SUBNET=172.33.10.0 + - ALLOWEDIPS=172.33.0.0/16 volumes: - - /path/to/appdata/config:/config - - /lib/modules:/lib/modules + - "wg-config:/config" + - "/lib/modules:/lib/modules" ports: - - 51820:51820/udp + - "51820:51820/udp" sysctls: - - net.ipv4.conf.all.src_valid_mark=1 \ No newline at end of file + - net.ipv4.conf.all.src_valid_mark=1 +volumes: + wg-config: {} diff --git a/setup-wizard.yml b/setup-wizard.yml new file mode 100644 index 00000000..c96087f8 --- /dev/null +++ b/setup-wizard.yml @@ -0,0 +1,20 @@ +version: "2" +fields: + - id: peers + target: + type: environment + name: PEERS + service: wireguard + title: Devices + description: >- + Please enter your names of your devices separated by commas and without whitespaces + required: true + + - id: domain + target: + type: environment + name: SERVERURL + service: node + title: Dappnode domain + description: >- + Dappnode domain name you would like to use (*.dyndns.dappnode.io domains are recommended). \ No newline at end of file From 8a13539702d6ad57acf247d8439eead6fad698b4 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 21 Jan 2021 22:57:20 +0100 Subject: [PATCH 07/57] Fixed bugs --- avatar-default.png | Bin 3377 -> 0 bytes avatar-wireguard.png | Bin 0 -> 40265 bytes dappnode_package.json | 4 ++++ docker-compose.yml | 7 +++---- releases.json | 8 ++++++++ setup-wizard.yml | 5 ++--- 6 files changed, 17 insertions(+), 7 deletions(-) delete mode 100644 avatar-default.png create mode 100644 avatar-wireguard.png create mode 100644 releases.json diff --git a/avatar-default.png b/avatar-default.png deleted file mode 100644 index ee2ac7328b3f6354ce179bc75bb571279d9ce411..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3377 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 diff --git a/avatar-wireguard.png b/avatar-wireguard.png new file mode 100644 index 0000000000000000000000000000000000000000..755e6e876f78af81ad6b14c652e136ce5e973a14 GIT binary patch literal 40265 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 Please enter your names of your devices separated by commas and without whitespaces @@ -14,7 +13,7 @@ fields: target: type: environment name: SERVERURL - service: node title: Dappnode domain description: >- - Dappnode domain name you would like to use (*.dyndns.dappnode.io domains are recommended). \ No newline at end of file + Dappnode domain name you would like to use (*.dyndns.dappnode.io domains are recommended). + required: true \ No newline at end of file From 3d07ae64d770a795a08d8b5bbb141c77724ece98 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 28 Jan 2021 03:07:45 +0100 Subject: [PATCH 08/57] Fixed hostname problem --- build/root/app/add-peer | 2 +- build/root/etc/cont-init.d/30-config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/root/app/add-peer b/build/root/app/add-peer index f7b069a5..d2574a5e 100755 --- a/build/root/app/add-peer +++ b/build/root/app/add-peer @@ -10,7 +10,7 @@ fi INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - SERVERURL=$(curl icanhazip.com) + SERVERURL=$(curl my.dappnode/global-envs/HOSTNAME) fi SERVERPORT=${SERVERPORT:-51820} if [ -z "$PEERDNS" ] || [ "$PEERDNS" = "auto" ]; then diff --git a/build/root/etc/cont-init.d/30-config b/build/root/etc/cont-init.d/30-config index 724d24b2..0bd6fd90 100644 --- a/build/root/etc/cont-init.d/30-config +++ b/build/root/etc/cont-init.d/30-config @@ -231,7 +231,7 @@ if [ -n "$PEERS" ]; then fi PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - SERVERURL=$(curl -s icanhazip.com) + SERVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" else echo "**** External server address is set to $SERVERURL ****" From 40e0a78e35f1871a99fc9704ffd952921fad97f0 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 28 Jan 2021 11:35:58 +0100 Subject: [PATCH 09/57] Splitting into two services --- build-api/Dockerfile | 14 ++++++++++++++ {build/root => build-api}/app/package-lock.json | 0 {build/root => build-api}/app/package.json | 0 {build/root => build-api}/app/src/server.ts | 0 {build/root => build-api}/app/tsconfig.json | 0 {build/root => build-api}/app/tslint.json | 0 {build => build-wg}/.dockerignore | 0 {build => build-wg}/.gitattributes | 0 {build => build-wg}/.gitignore | 0 {build => build-wg}/Dockerfile | 8 +------- {build => build-wg}/Dockerfile.aarch64 | 0 {build => build-wg}/Dockerfile.armhf | 0 {build => build-wg}/LICENSE | 0 {build => build-wg}/README.md | 0 {build => build-wg}/package_versions.txt | 0 {build => build-wg}/readme-vars.yml | 0 {build => build-wg}/root/app/add-peer | 0 {build => build-wg}/root/app/show-peer | 0 {build => build-wg}/root/defaults/Corefile | 0 {build => build-wg}/root/defaults/peer.conf | 0 {build => build-wg}/root/defaults/server.conf | 0 {build => build-wg}/root/donate.txt | 0 {build => build-wg}/root/etc/cont-init.d/30-config | 0 .../root/etc/services.d/coredns/run | 0 .../root/etc/services.d/wireguard/run | 0 build/root/app/.gitignore | 2 -- build/root/etc/services.d/nodejs-web/run | 3 --- docker-compose.yml | 11 ++++++++--- releases.json | 4 ++-- setup-wizard.yml | 9 --------- 30 files changed, 25 insertions(+), 26 deletions(-) create mode 100644 build-api/Dockerfile rename {build/root => build-api}/app/package-lock.json (100%) rename {build/root => build-api}/app/package.json (100%) rename {build/root => build-api}/app/src/server.ts (100%) rename {build/root => build-api}/app/tsconfig.json (100%) rename {build/root => build-api}/app/tslint.json (100%) rename {build => build-wg}/.dockerignore (100%) rename {build => build-wg}/.gitattributes (100%) rename {build => build-wg}/.gitignore (100%) rename {build => build-wg}/Dockerfile (93%) rename {build => build-wg}/Dockerfile.aarch64 (100%) rename {build => build-wg}/Dockerfile.armhf (100%) rename {build => build-wg}/LICENSE (100%) rename {build => build-wg}/README.md (100%) rename {build => build-wg}/package_versions.txt (100%) rename {build => build-wg}/readme-vars.yml (100%) rename {build => build-wg}/root/app/add-peer (100%) rename {build => build-wg}/root/app/show-peer (100%) rename {build => build-wg}/root/defaults/Corefile (100%) rename {build => build-wg}/root/defaults/peer.conf (100%) rename {build => build-wg}/root/defaults/server.conf (100%) rename {build => build-wg}/root/donate.txt (100%) rename {build => build-wg}/root/etc/cont-init.d/30-config (100%) rename {build => build-wg}/root/etc/services.d/coredns/run (100%) rename {build => build-wg}/root/etc/services.d/wireguard/run (100%) delete mode 100644 build/root/app/.gitignore delete mode 100644 build/root/etc/services.d/nodejs-web/run diff --git a/build-api/Dockerfile b/build-api/Dockerfile new file mode 100644 index 00000000..eead8ad4 --- /dev/null +++ b/build-api/Dockerfile @@ -0,0 +1,14 @@ +FROM node:12.18.1 + + +RUN mkdir -p /usr/ + +COPY . /usr + +WORKDIR /usr/app +RUN npm install + +EXPOSE 5000 + +ENTRYPOINT ["npm", "run"] +CMD ["start"] \ No newline at end of file diff --git a/build/root/app/package-lock.json b/build-api/app/package-lock.json similarity index 100% rename from build/root/app/package-lock.json rename to build-api/app/package-lock.json diff --git a/build/root/app/package.json b/build-api/app/package.json similarity index 100% rename from build/root/app/package.json rename to build-api/app/package.json diff --git a/build/root/app/src/server.ts b/build-api/app/src/server.ts similarity index 100% rename from build/root/app/src/server.ts rename to build-api/app/src/server.ts diff --git a/build/root/app/tsconfig.json b/build-api/app/tsconfig.json similarity index 100% rename from build/root/app/tsconfig.json rename to build-api/app/tsconfig.json diff --git a/build/root/app/tslint.json b/build-api/app/tslint.json similarity index 100% rename from build/root/app/tslint.json rename to build-api/app/tslint.json diff --git a/build/.dockerignore b/build-wg/.dockerignore similarity index 100% rename from build/.dockerignore rename to build-wg/.dockerignore diff --git a/build/.gitattributes b/build-wg/.gitattributes similarity index 100% rename from build/.gitattributes rename to build-wg/.gitattributes diff --git a/build/.gitignore b/build-wg/.gitignore similarity index 100% rename from build/.gitignore rename to build-wg/.gitignore diff --git a/build/Dockerfile b/build-wg/Dockerfile similarity index 93% rename from build/Dockerfile rename to build-wg/Dockerfile index 23d87952..47811d6d 100644 --- a/build/Dockerfile +++ b/build-wg/Dockerfile @@ -30,9 +30,7 @@ RUN \ openresolv \ perl \ pkg-config \ - qrencode \ - nodejs \ - npm && \ + qrencode && \ echo "**** install wireguard-tools ****" && \ if [ -z ${WIREGUARD_RELEASE+x} ]; then \ WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ @@ -62,9 +60,5 @@ RUN \ # add local files COPY /root / -RUN npm i -g npm@latest -RUN npm install --prefix=/app/ -RUN npm run build --prefix=/app/ - # ports and volumes EXPOSE 51820/udp diff --git a/build/Dockerfile.aarch64 b/build-wg/Dockerfile.aarch64 similarity index 100% rename from build/Dockerfile.aarch64 rename to build-wg/Dockerfile.aarch64 diff --git a/build/Dockerfile.armhf b/build-wg/Dockerfile.armhf similarity index 100% rename from build/Dockerfile.armhf rename to build-wg/Dockerfile.armhf diff --git a/build/LICENSE b/build-wg/LICENSE similarity index 100% rename from build/LICENSE rename to build-wg/LICENSE diff --git a/build/README.md b/build-wg/README.md similarity index 100% rename from build/README.md rename to build-wg/README.md diff --git a/build/package_versions.txt b/build-wg/package_versions.txt similarity index 100% rename from build/package_versions.txt rename to build-wg/package_versions.txt diff --git a/build/readme-vars.yml b/build-wg/readme-vars.yml similarity index 100% rename from build/readme-vars.yml rename to build-wg/readme-vars.yml diff --git a/build/root/app/add-peer b/build-wg/root/app/add-peer similarity index 100% rename from build/root/app/add-peer rename to build-wg/root/app/add-peer diff --git a/build/root/app/show-peer b/build-wg/root/app/show-peer similarity index 100% rename from build/root/app/show-peer rename to build-wg/root/app/show-peer diff --git a/build/root/defaults/Corefile b/build-wg/root/defaults/Corefile similarity index 100% rename from build/root/defaults/Corefile rename to build-wg/root/defaults/Corefile diff --git a/build/root/defaults/peer.conf b/build-wg/root/defaults/peer.conf similarity index 100% rename from build/root/defaults/peer.conf rename to build-wg/root/defaults/peer.conf diff --git a/build/root/defaults/server.conf b/build-wg/root/defaults/server.conf similarity index 100% rename from build/root/defaults/server.conf rename to build-wg/root/defaults/server.conf diff --git a/build/root/donate.txt b/build-wg/root/donate.txt similarity index 100% rename from build/root/donate.txt rename to build-wg/root/donate.txt diff --git a/build/root/etc/cont-init.d/30-config b/build-wg/root/etc/cont-init.d/30-config similarity index 100% rename from build/root/etc/cont-init.d/30-config rename to build-wg/root/etc/cont-init.d/30-config diff --git a/build/root/etc/services.d/coredns/run b/build-wg/root/etc/services.d/coredns/run similarity index 100% rename from build/root/etc/services.d/coredns/run rename to build-wg/root/etc/services.d/coredns/run diff --git a/build/root/etc/services.d/wireguard/run b/build-wg/root/etc/services.d/wireguard/run similarity index 100% rename from build/root/etc/services.d/wireguard/run rename to build-wg/root/etc/services.d/wireguard/run diff --git a/build/root/app/.gitignore b/build/root/app/.gitignore deleted file mode 100644 index 04c01ba7..00000000 --- a/build/root/app/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -dist/ \ No newline at end of file diff --git a/build/root/etc/services.d/nodejs-web/run b/build/root/etc/services.d/nodejs-web/run deleted file mode 100644 index c229d8b9..00000000 --- a/build/root/etc/services.d/nodejs-web/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/with-contenv bash - -npm start --prefix /app/ \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 74ecd0c6..ee3e084e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ version: "3.4" services: - wireguard.public.dappnode.eth: - build: ./build - image: "wireguard.public.dappnode.eth:0.1.0" + wireguard: + build: ./build-wg + image: "core.wireguard.public.dappnode.eth:0.1.0" restart: always cap_add: - NET_ADMIN @@ -23,5 +23,10 @@ services: - "51820:51820/udp" sysctls: - net.ipv4.conf.all.src_valid_mark=1 + api: + build: ./build-api + image: "api.wireguard.public.dappnode.eth:0.1.0" + volumes: + - "wg-config:/config" volumes: wg-config: {} diff --git a/releases.json b/releases.json index 29489485..23f74339 100644 --- a/releases.json +++ b/releases.json @@ -1,8 +1,8 @@ { "0.1.0": { - "hash": "/ipfs/Qmbwm5SusyTJzJZep5tQdxDgenvkWUgzSeuzzwnTG95YHF", + "hash": "/ipfs/QmcEcK8tEwYkeJWdvQaA6z5aaPdiJ23U6QtqTzzVoQEsJ2", "uploadedTo": { - "dappnode": "Thu, 21 Jan 2021 21:52:07 GMT" + "dappnode": "Thu, 28 Jan 2021 02:25:25 GMT" } } } diff --git a/setup-wizard.yml b/setup-wizard.yml index 848ace39..a90e414a 100644 --- a/setup-wizard.yml +++ b/setup-wizard.yml @@ -7,13 +7,4 @@ fields: title: Devices description: >- Please enter your names of your devices separated by commas and without whitespaces - required: true - - - id: domain - target: - type: environment - name: SERVERURL - title: Dappnode domain - description: >- - Dappnode domain name you would like to use (*.dyndns.dappnode.io domains are recommended). required: true \ No newline at end of file From a40a1ac3b254a40d82a51f4624b4fd74673b5c34 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 28 Jan 2021 11:38:21 +0100 Subject: [PATCH 10/57] Split into two services for optimisation --- build-api/Dockerfile | 25 ++++++++++++------------- build-api/{app => }/package-lock.json | 0 build-api/{app => }/package.json | 0 build-api/{app => }/src/server.ts | 0 build-api/{app => }/tsconfig.json | 0 build-api/{app => }/tslint.json | 0 docker-compose.yml | 2 +- 7 files changed, 13 insertions(+), 14 deletions(-) rename build-api/{app => }/package-lock.json (100%) rename build-api/{app => }/package.json (100%) rename build-api/{app => }/src/server.ts (100%) rename build-api/{app => }/tsconfig.json (100%) rename build-api/{app => }/tslint.json (100%) diff --git a/build-api/Dockerfile b/build-api/Dockerfile index eead8ad4..b994bac7 100644 --- a/build-api/Dockerfile +++ b/build-api/Dockerfile @@ -1,14 +1,13 @@ -FROM node:12.18.1 - - -RUN mkdir -p /usr/ - -COPY . /usr - -WORKDIR /usr/app +FROM node:12-alpine AS ts-sample-builder +WORKDIR /app +COPY . . RUN npm install - -EXPOSE 5000 - -ENTRYPOINT ["npm", "run"] -CMD ["start"] \ No newline at end of file +RUN npm run clean +RUN npm run build +# Our Second stage, that creates an image for production +FROM node:12-alpine AS ts-sample-prod +WORKDIR /app +COPY --from=ts-sample-builder ./app/dist ./dist +COPY package* ./ +RUN npm install --production +CMD npm start \ No newline at end of file diff --git a/build-api/app/package-lock.json b/build-api/package-lock.json similarity index 100% rename from build-api/app/package-lock.json rename to build-api/package-lock.json diff --git a/build-api/app/package.json b/build-api/package.json similarity index 100% rename from build-api/app/package.json rename to build-api/package.json diff --git a/build-api/app/src/server.ts b/build-api/src/server.ts similarity index 100% rename from build-api/app/src/server.ts rename to build-api/src/server.ts diff --git a/build-api/app/tsconfig.json b/build-api/tsconfig.json similarity index 100% rename from build-api/app/tsconfig.json rename to build-api/tsconfig.json diff --git a/build-api/app/tslint.json b/build-api/tslint.json similarity index 100% rename from build-api/app/tslint.json rename to build-api/tslint.json diff --git a/docker-compose.yml b/docker-compose.yml index ee3e084e..46a2e5cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.4" services: wireguard: build: ./build-wg - image: "core.wireguard.public.dappnode.eth:0.1.0" + image: "wireguard.wireguard.public.dappnode.eth:0.1.0" restart: always cap_add: - NET_ADMIN From 64317533be86664f149029b0d4f57ee6d5435dbc Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 28 Jan 2021 15:02:17 +0100 Subject: [PATCH 11/57] Adding compatibiliy mode --- build-wg/root/etc/cont-init.d/30-config | 6 ++++++ docker-compose.yml | 1 + setup-wizard.yml | 1 + 3 files changed, 8 insertions(+) diff --git a/build-wg/root/etc/cont-init.d/30-config b/build-wg/root/etc/cont-init.d/30-config index 0bd6fd90..ab8f0c68 100644 --- a/build-wg/root/etc/cont-init.d/30-config +++ b/build-wg/root/etc/cont-init.d/30-config @@ -134,6 +134,12 @@ DUDE fi cd /app echo "**** Building the module ****" + if [ -z ${WIREGUARD_RELEASE} ] ; then + echo "Wireguard release set, checking out correct version" + cd wireguard-linux-compat + git checkout $WIREGUARD_RELEASE + cd .. + fi make -C wireguard-linux-compat/src -j$(nproc) make -C wireguard-linux-compat/src install echo "**** Let's test our new module. ****" diff --git a/docker-compose.yml b/docker-compose.yml index 46a2e5cb..5fff0e3a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: environment: - PEERS=dappnode_admin - SERVERURL= + - WIREGUARD_RELEASE= - PUID=1000 - PGID=1000 - SERVERPORT=51820 diff --git a/setup-wizard.yml b/setup-wizard.yml index a90e414a..de9aed90 100644 --- a/setup-wizard.yml +++ b/setup-wizard.yml @@ -4,6 +4,7 @@ fields: target: type: environment name: PEERS + service: wireguard title: Devices description: >- Please enter your names of your devices separated by commas and without whitespaces From c5b3f09b2d9afa04e0c24f236fae3894a995b9dc Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Mon, 1 Feb 2021 12:15:05 +0100 Subject: [PATCH 12/57] Fixed build --- build-api/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build-api/Dockerfile b/build-api/Dockerfile index b994bac7..a38fc506 100644 --- a/build-api/Dockerfile +++ b/build-api/Dockerfile @@ -1,13 +1,13 @@ -FROM node:12-alpine AS ts-sample-builder +FROM node:12 AS builder WORKDIR /app COPY . . RUN npm install RUN npm run clean RUN npm run build # Our Second stage, that creates an image for production -FROM node:12-alpine AS ts-sample-prod +FROM node:12-alpine WORKDIR /app -COPY --from=ts-sample-builder ./app/dist ./dist +COPY --from=builder ./app/dist ./dist COPY package* ./ RUN npm install --production -CMD npm start \ No newline at end of file +CMD npm start From ffced73575f72d32c69f16b89ece6fb770df6f9d Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Sun, 14 Feb 2021 01:19:23 +0100 Subject: [PATCH 13/57] Auto retry building modules --- build-wg/root/etc/cont-init.d/30-config | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/build-wg/root/etc/cont-init.d/30-config b/build-wg/root/etc/cont-init.d/30-config index ab8f0c68..2d013b25 100644 --- a/build-wg/root/etc/cont-init.d/30-config +++ b/build-wg/root/etc/cont-init.d/30-config @@ -133,15 +133,19 @@ DUDE openssl req -new -nodes -utf8 -sha512 -days 36500 -batch -x509 -config x509.genkey -outform DER -out signing_key.x509 -keyout signing_key.pem fi cd /app - echo "**** Building the module ****" - if [ -z ${WIREGUARD_RELEASE} ] ; then - echo "Wireguard release set, checking out correct version" - cd wireguard-linux-compat - git checkout $WIREGUARD_RELEASE - cd .. - fi - make -C wireguard-linux-compat/src -j$(nproc) - make -C wireguard-linux-compat/src install + for release in "" "v1.0.20200520" "v1.0.20200330" "v0.0.20200105"; do + echo "**** Building the module ****" + if ! [ -z ${release} ] ; then + echo "Wireguard release ${release} set, checking out correct version" + cd wireguard-linux-compat + git checkout $release + cd .. + fi + make -C wireguard-linux-compat/src -j$(nproc) && returncode=$? || returncode=$? + if [ $returncode -ne 0 ]; then continue; fi + make -C wireguard-linux-compat/src install && returncode=$? || returncode=$? + if [ $returncode -eq 0 ] ; then break; fi + done echo "**** Let's test our new module. ****" ip link del dev test 2>/dev/null if ip link add dev test type wireguard; then From c510847d0e66ca3b1a37c233f34c75509c163c6d Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Sun, 14 Feb 2021 01:43:03 +0100 Subject: [PATCH 14/57] Retry domain fetch --- build-wg/root/etc/cont-init.d/30-config | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build-wg/root/etc/cont-init.d/30-config b/build-wg/root/etc/cont-init.d/30-config index 2d013b25..00a163a7 100644 --- a/build-wg/root/etc/cont-init.d/30-config +++ b/build-wg/root/etc/cont-init.d/30-config @@ -241,7 +241,12 @@ if [ -n "$PEERS" ]; then fi PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - SERVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) + for i in {1..20}; do + echo "Fetching DAppNode domain..." + SERRVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) + if [ ! -z $SERRVERURL ]; then break; fi + sleep 2 + done echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" else echo "**** External server address is set to $SERVERURL ****" From 7e0727c22d224615c3f0d5cc53e7ac8c60e77cd6 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Sun, 14 Feb 2021 01:50:51 +0100 Subject: [PATCH 15/57] Tipfeller --- build-wg/root/etc/cont-init.d/30-config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-wg/root/etc/cont-init.d/30-config b/build-wg/root/etc/cont-init.d/30-config index 00a163a7..933062b1 100644 --- a/build-wg/root/etc/cont-init.d/30-config +++ b/build-wg/root/etc/cont-init.d/30-config @@ -242,9 +242,9 @@ if [ -n "$PEERS" ]; then PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then for i in {1..20}; do - echo "Fetching DAppNode domain..." - SERRVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) - if [ ! -z $SERRVERURL ]; then break; fi + echo "**** Fetching DAppNode domain..." + SERVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) + if [ ! -z $SERVERURL ]; then break; fi sleep 2 done echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" From 6c2b1c6b38e1f0bcbca43043f231bc3f5d59fd19 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Wed, 17 Feb 2021 23:35:22 +0100 Subject: [PATCH 16/57] Changed subnet to private --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5fff0e3a..7c1e8911 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: - PGID=1000 - SERVERPORT=51820 - PEERDNS=172.33.1.2 - - INTERNAL_SUBNET=172.34.1.0 + - INTERNAL_SUBNET=10.24.0.0 - ALLOWEDIPS=172.33.0.0/16 volumes: - "wg-config:/config" From 32b4eebea8863cca2feb68f4966239e7341379d9 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 25 Feb 2021 15:28:00 +0100 Subject: [PATCH 17/57] Optimize the webserver api --- build-api/.dockerignore | 5 + build-api/.gitignore | 2 + build-api/Dockerfile | 24 +- build-api/index.ts | 28 + build-api/package-lock.json | 1913 ----------------------------------- build-api/package.json | 10 +- build-api/src/server.ts | 49 - build-api/tsconfig.json | 21 +- build-api/tslint.json | 3 +- build-api/yarn.lock | 1399 +++++++++++++++++++++++++ 10 files changed, 1462 insertions(+), 1992 deletions(-) create mode 100644 build-api/.dockerignore create mode 100644 build-api/.gitignore create mode 100644 build-api/index.ts delete mode 100644 build-api/package-lock.json delete mode 100644 build-api/src/server.ts create mode 100644 build-api/yarn.lock diff --git a/build-api/.dockerignore b/build-api/.dockerignore new file mode 100644 index 00000000..fdcbda65 --- /dev/null +++ b/build-api/.dockerignore @@ -0,0 +1,5 @@ +dist/ +node_modules/ +Dockerfile +.dockerignore +.gitignore diff --git a/build-api/.gitignore b/build-api/.gitignore new file mode 100644 index 00000000..04c01ba7 --- /dev/null +++ b/build-api/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ \ No newline at end of file diff --git a/build-api/Dockerfile b/build-api/Dockerfile index a38fc506..8a1f9b68 100644 --- a/build-api/Dockerfile +++ b/build-api/Dockerfile @@ -1,13 +1,19 @@ -FROM node:12 AS builder +FROM node:12-alpine AS builder WORKDIR /app COPY . . -RUN npm install -RUN npm run clean -RUN npm run build +RUN yarn +RUN yarn build + +RUN rm -rf node_modules && yarn --production + + # Our Second stage, that creates an image for production -FROM node:12-alpine +FROM alpine WORKDIR /app -COPY --from=builder ./app/dist ./dist -COPY package* ./ -RUN npm install --production -CMD npm start + +RUN apk add --update --no-cache nodejs + +COPY --from=builder /app/dist/ ./ +COPY --from=builder /app/node_modules/ ./node_modules + +ENTRYPOINT [ "node", "index" ] diff --git a/build-api/index.ts b/build-api/index.ts new file mode 100644 index 00000000..e1f8a383 --- /dev/null +++ b/build-api/index.ts @@ -0,0 +1,28 @@ +import express from "express"; +import cors from "cors"; +import path from "path"; + +const port = process.env.SERVER_PORT || 80; +const dataDir: string = process.env.DATA_DIR || "/config"; + +const app = express(); +app.use(cors()); + +app.get("/:device/:mode?", (req: express.Request, res: express.Response) => { + const { mode, device } = req.params; + const fileExt = mode === "qr" ? "png" : "conf"; + const filePath = path.join( + dataDir, + `peer_${device}`, + `peer_${device}.${fileExt}` + ); + + try { + res.status(200).sendFile(filePath); + } catch (e) { + if (e.code === "ENOENT") res.status(404).send("Not found"); + else res.status(500).send(e.stack); + } +}); + +app.listen(port, () => console.log(`Listening on port ${port}`)); diff --git a/build-api/package-lock.json b/build-api/package-lock.json deleted file mode 100644 index dc6deb43..00000000 --- a/build-api/package-lock.json +++ /dev/null @@ -1,1913 +0,0 @@ -{ - "name": "wireguard-http", - "version": "0.1.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } - } - }, - "@eslint/eslintrc": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", - "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.4", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.4", - "fastq": "^1.6.0" - } - }, - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bunyan": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.6.tgz", - "integrity": "sha512-YiozPOOsS6bIuz31ilYqR5SlLif4TBWsousN2aCWLi5233nZSX19tFbcQUPdR7xJ8ypPyxkCGNxg0CIV5n9qxQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.34", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", - "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/cors": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz", - "integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg==", - "dev": true - }, - "@types/express": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz", - "integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.18", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz", - "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true - }, - "@types/mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", - "dev": true - }, - "@types/node": { - "version": "14.14.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.21.tgz", - "integrity": "sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A==", - "dev": true - }, - "@types/qs": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", - "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", - "dev": true - }, - "@types/serve-static": { - "version": "1.13.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.8.tgz", - "integrity": "sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA==", - "dev": true, - "requires": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz", - "integrity": "sha512-ygqDUm+BUPvrr0jrXqoteMqmIaZ/bixYOc3A4BRwzEPTZPi6E+n44rzNZWaB0YvtukgP+aoj0i/fyx7FkM2p1w==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.13.0", - "@typescript-eslint/scope-manager": "4.13.0", - "debug": "^4.1.1", - "functional-red-black-tree": "^1.0.1", - "lodash": "^4.17.15", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "tsutils": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.1.tgz", - "integrity": "sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.13.0.tgz", - "integrity": "sha512-/ZsuWmqagOzNkx30VWYV3MNB/Re/CGv/7EzlqZo5RegBN8tMuPaBgNK6vPBCQA8tcYrbsrTdbx3ixMRRKEEGVw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.13.0", - "@typescript-eslint/types": "4.13.0", - "@typescript-eslint/typescript-estree": "4.13.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.13.0.tgz", - "integrity": "sha512-KO0J5SRF08pMXzq9+abyHnaGQgUJZ3Z3ax+pmqz9vl81JxmTTOUfQmq7/4awVfq09b6C4owNlOgOwp61pYRBSg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.13.0", - "@typescript-eslint/types": "4.13.0", - "@typescript-eslint/typescript-estree": "4.13.0", - "debug": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.13.0.tgz", - "integrity": "sha512-UpK7YLG2JlTp/9G4CHe7GxOwd93RBf3aHO5L+pfjIrhtBvZjHKbMhBXTIQNkbz7HZ9XOe++yKrXutYm5KmjWgQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.13.0", - "@typescript-eslint/visitor-keys": "4.13.0" - } - }, - "@typescript-eslint/types": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.13.0.tgz", - "integrity": "sha512-/+aPaq163oX+ObOG00M0t9tKkOgdv9lq0IQv/y4SqGkAXmhFmCfgsELV7kOCTb2vVU5VOmVwXBXJTDr353C1rQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.13.0.tgz", - "integrity": "sha512-9A0/DFZZLlGXn5XA349dWQFwPZxcyYyCFX5X88nWs2uachRDwGeyPz46oTsm9ZJE66EALvEns1lvBwa4d9QxMg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.13.0", - "@typescript-eslint/visitor-keys": "4.13.0", - "debug": "^4.1.1", - "globby": "^11.0.1", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "tsutils": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.1.tgz", - "integrity": "sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.13.0.tgz", - "integrity": "sha512-6RoxWK05PAibukE7jElqAtNMq+RWZyqJ6Q/GdIxaiUj2Ept8jh8+FUVlbq9WxMYxkmEOPvCE5cRSyupMpwW31g==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.13.0", - "eslint-visitor-keys": "^2.0.0" - } - }, - "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" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "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=" - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "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" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "bunyan": { - "version": "1.8.15", - "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", - "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", - "requires": { - "dtrace-provider": "~0.8", - "moment": "^2.19.3", - "mv": "~2", - "safe-json-stringify": "~1" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "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==", - "dev": true, - "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==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "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==", - "dev": true, - "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=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "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=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "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" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "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=" - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dtrace-provider": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", - "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", - "optional": true, - "requires": { - "nan": "^2.14.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "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==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "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=", - "dev": true - }, - "eslint": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz", - "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.4", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "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" - } - }, - "express-validator": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", - "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", - "requires": { - "lodash": "^4.17.20", - "validator": "^13.5.2" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", - "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", - "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "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" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", - "dev": true - }, - "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.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "optional": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "globby": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", - "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "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" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "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" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "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-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "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==", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^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=" - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "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.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" - }, - "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", - "requires": { - "mime-db": "1.45.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "optional": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "optional": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mv": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", - "optional": true, - "requires": { - "mkdirp": "~0.5.1", - "ncp": "~2.0.0", - "rimraf": "~2.4.0" - }, - "dependencies": { - "rimraf": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", - "optional": true, - "requires": { - "glob": "^6.0.1" - } - } - } - }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "optional": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", - "optional": true - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "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" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "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=" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "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" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "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" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "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==" - }, - "safe-json-stringify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", - "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "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": { - "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": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "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==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "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==", - "dev": true, - "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==", - "dev": true - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "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==", - "dev": true, - "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==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", - "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", - "dev": true, - "requires": { - "ajv": "^7.0.2", - "lodash": "^4.17.20", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "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.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tslint-microsoft-contrib": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz", - "integrity": "sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==", - "dev": true, - "requires": { - "tsutils": "^2.27.2 <2.29.0" - } - }, - "tslint-sonarts": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/tslint-sonarts/-/tslint-sonarts-1.9.0.tgz", - "integrity": "sha512-CJWt+IiYI8qggb2O/JPkS6CkC5DY1IcqRsm9EHJ+AxoWK70lvtP7jguochyNDMP2vIz/giGdWCfEM39x/I/Vnw==", - "dev": true, - "requires": { - "immutable": "^3.8.2" - } - }, - "tsutils": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz", - "integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "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" - } - }, - "typescript": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", - "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", - "dev": true - }, - "typestrict": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typestrict/-/typestrict-1.0.2.tgz", - "integrity": "sha512-4wEr84NPc0ldINrgwgSBTmbWPiGVbwO3c9xumM0ujp0DlzhTs3jUT0NtVBOd5UXneSXcStNJWj80zerbW2YR6Q==", - "dev": true, - "requires": { - "tslint-microsoft-contrib": "^5.0.3", - "tslint-sonarts": "^1.8.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", - "dev": true - }, - "validator": { - "version": "13.5.2", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", - "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } -} diff --git a/build-api/package.json b/build-api/package.json index 88d0c8d9..7a893cf0 100644 --- a/build-api/package.json +++ b/build-api/package.json @@ -5,29 +5,23 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "clean": "rimraf ./dist", - "build": "npm run clean && tsc", + "build": "tsc", "start": "node ./dist/server.js", "lint": "eslint . --ext .ts" }, "author": "lg@shardlabs.io", "license": "MIT", "dependencies": { - "bunyan": "^1.8.15", "cors": "^2.8.5", - "express": "^4.17.1", - "express-validator": "^6.9.2" + "express": "^4.17.1" }, "devDependencies": { - "@types/bunyan": "^1.8.6", "@types/cors": "2.8.9", "@types/express": "^4.17.11", "@types/node": "^14.14.21", "@typescript-eslint/eslint-plugin": "^4.6.1", "@typescript-eslint/parser": "^4.6.1", - "rimraf": "^3.0.2", "eslint": "^7.13.0", - "typestrict": "^1.0.2", "typescript": "4.1.3" } } diff --git a/build-api/src/server.ts b/build-api/src/server.ts deleted file mode 100644 index 5bf848ff..00000000 --- a/build-api/src/server.ts +++ /dev/null @@ -1,49 +0,0 @@ -import express from 'express'; -import { param, validationResult } from 'express-validator'; -import cors from 'cors'; -import path from 'path'; -import Logger from 'bunyan'; - -const app = express(); - -const port = process.env.SERVER_PORT || 80; -const dataDir: string = process.env.DATA_DIR || "/config"; -app.use(cors()) - -let silent; -const log = Logger.createLogger({ - name: "Server", - streams: [{ - stream: process.stdout, - level: silent ? 'fatal' : 30 - }] - }); - - -app.get('/:mode/:device', - [ - param('mode').isIn(['conf', 'qr']) - ], - (req: express.Request, res: express.Response) => { - const errors = validationResult(req); - if (!errors.isEmpty()) { - return res.status(400).json({ errors: errors.array() }); - } - - let ext = 'conf'; - - if (req.params.mode === 'qr') ext = 'png'; - - const device: string = req.params.device; - - try { - res.status(200).sendFile(path.join(dataDir, `peer_${device}/peer_${device}.${ext}`)); - } catch(error: any){ - res.status(404).end('Not found'); - } - }); - - -app.listen(port, () => log.info({loc: '[LISTEN]'}, `Injector listening on port ${port}!`)) - -export default app; diff --git a/build-api/tsconfig.json b/build-api/tsconfig.json index bc81cc0b..7a9cfd86 100644 --- a/build-api/tsconfig.json +++ b/build-api/tsconfig.json @@ -1,12 +1,11 @@ { - "compilerOptions": { - "allowJs": true, - "target": "es5", - "sourceMap": true, - "esModuleInterop": true, - "strict": true, - "outDir": "dist" - }, - "include": ["./src"] - } - \ No newline at end of file + "compilerOptions": { + "allowJs": true, + "target": "es5", + "sourceMap": true, + "esModuleInterop": true, + "strict": true, + "outDir": "dist" + }, + "include": ["./src", "index.ts"] +} diff --git a/build-api/tslint.json b/build-api/tslint.json index 816e57c0..a29704ff 100644 --- a/build-api/tslint.json +++ b/build-api/tslint.json @@ -1,5 +1,4 @@ { - "extends": "typestrict", "rules": { "no-debugger": true, "mocha-avoid-only": true, @@ -10,4 +9,4 @@ }, "no-use-before-declare": false } -} \ No newline at end of file +} diff --git a/build-api/yarn.lock b/build-api/yarn.lock new file mode 100644 index 00000000..47300b3d --- /dev/null +++ b/build-api/yarn.lock @@ -0,0 +1,1399 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/highlight@^7.10.4": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" + integrity sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.20" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@nodelib/fs.scandir@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" + integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== + dependencies: + "@nodelib/fs.stat" "2.0.4" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" + integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" + integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== + dependencies: + "@nodelib/fs.scandir" "2.1.4" + fastq "^1.6.0" + +"@types/body-parser@*": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" + integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.34" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901" + integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ== + dependencies: + "@types/node" "*" + +"@types/cors@2.8.9": + version "2.8.9" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.9.tgz#4bd1fcac72eca8d5bec93e76c7fdcbdc1bc2cd4a" + integrity sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg== + +"@types/express-serve-static-core@^4.17.18": + version "4.17.18" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40" + integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@^4.17.11": + version "4.17.11" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.11.tgz#debe3caa6f8e5fcda96b47bd54e2f40c4ee59545" + integrity sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/json-schema@^7.0.3": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== + +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + +"@types/node@*", "@types/node@^14.14.21": + version "14.14.31" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055" + integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g== + +"@types/qs@*": + version "6.9.5" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" + integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== + +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + +"@types/serve-static@*": + version "1.13.9" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" + integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@^4.6.1": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz#981b26b4076c62a5a55873fbef3fe98f83360c61" + integrity sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q== + dependencies: + "@typescript-eslint/experimental-utils" "4.15.2" + "@typescript-eslint/scope-manager" "4.15.2" + debug "^4.1.1" + functional-red-black-tree "^1.0.1" + lodash "^4.17.15" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz#5efd12355bd5b535e1831282e6cf465b9a71cf36" + integrity sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/scope-manager" "4.15.2" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/typescript-estree" "4.15.2" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^4.6.1": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.15.2.tgz#c804474321ef76a3955aec03664808f0d6e7872e" + integrity sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q== + dependencies: + "@typescript-eslint/scope-manager" "4.15.2" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/typescript-estree" "4.15.2" + debug "^4.1.1" + +"@typescript-eslint/scope-manager@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz#5725bda656995960ae1d004bfd1cd70320f37f4f" + integrity sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ== + dependencies: + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/visitor-keys" "4.15.2" + +"@typescript-eslint/types@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.2.tgz#04acf3a2dc8001a88985291744241e732ef22c60" + integrity sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ== + +"@typescript-eslint/typescript-estree@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz#c2f7a1e94f3428d229d5ecff3ead6581ee9b62fa" + integrity sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw== + dependencies: + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/visitor-keys" "4.15.2" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/visitor-keys@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz#3d1c7979ce75bf6acf9691109bd0d6b5706192b9" + integrity sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg== + dependencies: + "@typescript-eslint/types" "4.15.2" + eslint-visitor-keys "^2.0.0" + +accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.1.1.tgz#1e6b37a454021fa9941713f38b952fc1c8d32a84" + integrity sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + 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" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.0.1, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@^5.0.0, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.13.0: + version "7.20.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.20.0.tgz#db07c4ca4eda2e2316e7aa57ac7fc91ec550bdc7" + integrity sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.3.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + file-entry-cache "^6.0.0" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.20" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + 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" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.1.1: + version "3.2.5" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" + integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" + integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + 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" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +glob-parent@^5.0.0, glob-parent@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +globby@^11.0.1: + version "11.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83" + integrity sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lodash@^4.17.15, lodash@^4.17.20: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +mime-db@1.46.0: + version "1.46.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" + integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== + +mime-types@~2.1.24: + version "2.1.29" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" + integrity sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ== + dependencies: + mime-db "1.46.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +object-assign@^4: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +proxy-addr@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.1" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +queue-microtask@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.2.tgz#abf64491e6ecf0f38a6502403d4cda04f372dfd3" + integrity sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^7.2.1, semver@^7.3.2: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + 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" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +table@^6.0.4: + version "6.0.7" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== + dependencies: + ajv "^7.0.2" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.17.1: + version "3.20.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.20.0.tgz#ea03ea45462e146b53d70ce0893de453ff24f698" + integrity sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typescript@4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== From e9551c5d0cf814382b8ba3ec0287531573ba3d29 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 25 Feb 2021 15:32:26 +0100 Subject: [PATCH 18/57] Add release CI --- .github/workflows/main.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..afaa9f68 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,33 @@ +name: "Main" +on: + pull_request: + push: + branches: + - "main" + - "master" + - "v[0-9]+.[0-9]+.[0-9]+" + paths-ignore: + - "README.md" + +jobs: + build-test: + runs-on: ubuntu-latest + name: Build test + if: github.event_name != 'push' + steps: + - uses: actions/checkout@v2 + - run: npx @dappnode/dappnodesdk build --skip_save + + release: + name: Release + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - uses: actions/checkout@v2 + - name: Publish + run: npx @dappnode/dappnodesdk publish patch --dappnode_team_preset + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PINATA_API_KEY: ${{ secrets.PINATA_API_KEY }} + PINATA_SECRET_API_KEY: ${{ secrets.PINATA_SECRET_API_KEY }} + DEVELOPER_ADDRESS: "0xf35960302a07022aba880dffaec2fdd64d5bf1c1" From 83ba3cc6c19eca276cd71683717fe3cfffb1e5ed Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 4 Mar 2021 01:40:38 +0100 Subject: [PATCH 19/57] Buildx and arm compatibility --- build-wg/Dockerfile | 3 ++- dappnode_package.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build-wg/Dockerfile b/build-wg/Dockerfile index 47811d6d..37f21dc5 100644 --- a/build-wg/Dockerfile +++ b/build-wg/Dockerfile @@ -4,6 +4,7 @@ FROM ghcr.io/linuxserver/baseimage-ubuntu:bionic ARG BUILD_DATE ARG VERSION ARG WIREGUARD_RELEASE +ARG TARGETPLATFORM LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" LABEL maintainer="aptalca" @@ -48,7 +49,7 @@ RUN \ | awk '/tag_name/{print $4;exit}' FS='[""]' | awk '{print substr($1,2); }') && \ curl -o \ /tmp/coredns.tar.gz -L \ - "https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_amd64.tgz" && \ + "https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_$(echo ${TARGETPLATFORM:-linux/amd64} | sed 's:/:_:g' | sed 's/arm_v7/arm/').tgz" && \ tar xf \ /tmp/coredns.tar.gz -C \ /app && \ diff --git a/dappnode_package.json b/dappnode_package.json index 7d6307f4..f89ca030 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -5,6 +5,7 @@ "type": "service", "author": "Shardlabs", "categories": ["Developer tools"], + "architectures": ["linux/amd64", "linux/arm64"], "links": { "homepage": "https://github.com/Shard-Labs/docker-wireguard" }, From a7846211e79a287d34cdfcd74b24841da9a99b8e Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 9 Mar 2021 23:59:03 +0100 Subject: [PATCH 20/57] Move to dnp repo and core --- dappnode_package.json | 4 ++-- docker-compose.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index f89ca030..63d690a8 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -1,8 +1,8 @@ { - "name": "wireguard.public.dappnode.eth", + "name": "wireguard.dnp.dappnode.eth", "version": "0.1.0", "description": "Wireguard for DAppNode", - "type": "service", + "type": "dncore", "author": "Shardlabs", "categories": ["Developer tools"], "architectures": ["linux/amd64", "linux/arm64"], diff --git a/docker-compose.yml b/docker-compose.yml index 7c1e8911..fa8e987d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.4" services: wireguard: build: ./build-wg - image: "wireguard.wireguard.public.dappnode.eth:0.1.0" + image: "wireguard.wireguard.dnp.dappnode.eth:0.1.0" restart: always cap_add: - NET_ADMIN @@ -26,7 +26,7 @@ services: - net.ipv4.conf.all.src_valid_mark=1 api: build: ./build-api - image: "api.wireguard.public.dappnode.eth:0.1.0" + image: "api.wireguard.dnp.dappnode.eth:0.1.0" volumes: - "wg-config:/config" volumes: From 92d4dfc5907700fdef93308dd57955919be90ac2 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 11 Mar 2021 11:25:35 +0100 Subject: [PATCH 21/57] Allow graceful fast shutdown --- build-api/index.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build-api/index.ts b/build-api/index.ts index e1f8a383..a1b61444 100644 --- a/build-api/index.ts +++ b/build-api/index.ts @@ -25,4 +25,11 @@ app.get("/:device/:mode?", (req: express.Request, res: express.Response) => { } }); -app.listen(port, () => console.log(`Listening on port ${port}`)); +const server = app.listen(port, () => console.log(`Listening on port ${port}`)); + +process.on("SIGTERM", shutdown); +process.on("SIGINT", shutdown); +function shutdown() { + console.log("Closing server..."); + server.close((err) => console.log(err || "Bye")); +} From 06176bcc0a338f636a45892148d73692ffa640f1 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 11 Mar 2021 11:43:01 +0100 Subject: [PATCH 22/57] Moving files --- build-wg/.dockerignore => .dockerignore | 1 + build-wg/.gitattributes => .gitattributes | 0 .gitignore | 43 ++++++++++++++++++ build-wg/Dockerfile => Dockerfile | 0 .../Dockerfile.aarch64 => Dockerfile.aarch64 | 0 build-wg/Dockerfile.armhf => Dockerfile.armhf | 0 build-wg/LICENSE => LICENSE | 0 build-wg/README.md => README.md | 0 {build-api => api}/.dockerignore | 0 {build-api => api}/.gitignore | 0 {build-api => api}/Dockerfile | 0 {build-api => api}/index.ts | 0 {build-api => api}/package.json | 0 {build-api => api}/tsconfig.json | 0 {build-api => api}/tslint.json | 0 {build-api => api}/yarn.lock | 0 build-wg/.gitignore | 45 ------------------- docker-compose.yml | 4 +- ...ckage_versions.txt => package_versions.txt | 0 build-wg/readme-vars.yml => readme-vars.yml | 0 releases.json | 4 +- {build-wg/root => root}/app/add-peer | 0 {build-wg/root => root}/app/show-peer | 0 {build-wg/root => root}/defaults/Corefile | 0 {build-wg/root => root}/defaults/peer.conf | 0 {build-wg/root => root}/defaults/server.conf | 0 {build-wg/root => root}/donate.txt | 0 .../root => root}/etc/cont-init.d/30-config | 0 .../root => root}/etc/services.d/coredns/run | 0 .../etc/services.d/wireguard/run | 0 30 files changed, 48 insertions(+), 49 deletions(-) rename build-wg/.dockerignore => .dockerignore (97%) rename build-wg/.gitattributes => .gitattributes (100%) rename build-wg/Dockerfile => Dockerfile (100%) rename build-wg/Dockerfile.aarch64 => Dockerfile.aarch64 (100%) rename build-wg/Dockerfile.armhf => Dockerfile.armhf (100%) rename build-wg/LICENSE => LICENSE (100%) rename build-wg/README.md => README.md (100%) rename {build-api => api}/.dockerignore (100%) rename {build-api => api}/.gitignore (100%) rename {build-api => api}/Dockerfile (100%) rename {build-api => api}/index.ts (100%) rename {build-api => api}/package.json (100%) rename {build-api => api}/tsconfig.json (100%) rename {build-api => api}/tslint.json (100%) rename {build-api => api}/yarn.lock (100%) delete mode 100644 build-wg/.gitignore rename build-wg/package_versions.txt => package_versions.txt (100%) rename build-wg/readme-vars.yml => readme-vars.yml (100%) rename {build-wg/root => root}/app/add-peer (100%) rename {build-wg/root => root}/app/show-peer (100%) rename {build-wg/root => root}/defaults/Corefile (100%) rename {build-wg/root => root}/defaults/peer.conf (100%) rename {build-wg/root => root}/defaults/server.conf (100%) rename {build-wg/root => root}/donate.txt (100%) rename {build-wg/root => root}/etc/cont-init.d/30-config (100%) rename {build-wg/root => root}/etc/services.d/coredns/run (100%) rename {build-wg/root => root}/etc/services.d/wireguard/run (100%) diff --git a/build-wg/.dockerignore b/.dockerignore similarity index 97% rename from build-wg/.dockerignore rename to .dockerignore index 26260e27..bb0698c1 100644 --- a/build-wg/.dockerignore +++ b/.dockerignore @@ -6,3 +6,4 @@ READMETEMPLATE.md README.md root/app/node_modules root/app/dist +api \ No newline at end of file diff --git a/build-wg/.gitattributes b/.gitattributes similarity index 100% rename from build-wg/.gitattributes rename to .gitattributes diff --git a/.gitignore b/.gitignore index 3a8e2f72..77affc59 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,45 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk # DAppNodeSDK release directories build_* diff --git a/build-wg/Dockerfile b/Dockerfile similarity index 100% rename from build-wg/Dockerfile rename to Dockerfile diff --git a/build-wg/Dockerfile.aarch64 b/Dockerfile.aarch64 similarity index 100% rename from build-wg/Dockerfile.aarch64 rename to Dockerfile.aarch64 diff --git a/build-wg/Dockerfile.armhf b/Dockerfile.armhf similarity index 100% rename from build-wg/Dockerfile.armhf rename to Dockerfile.armhf diff --git a/build-wg/LICENSE b/LICENSE similarity index 100% rename from build-wg/LICENSE rename to LICENSE diff --git a/build-wg/README.md b/README.md similarity index 100% rename from build-wg/README.md rename to README.md diff --git a/build-api/.dockerignore b/api/.dockerignore similarity index 100% rename from build-api/.dockerignore rename to api/.dockerignore diff --git a/build-api/.gitignore b/api/.gitignore similarity index 100% rename from build-api/.gitignore rename to api/.gitignore diff --git a/build-api/Dockerfile b/api/Dockerfile similarity index 100% rename from build-api/Dockerfile rename to api/Dockerfile diff --git a/build-api/index.ts b/api/index.ts similarity index 100% rename from build-api/index.ts rename to api/index.ts diff --git a/build-api/package.json b/api/package.json similarity index 100% rename from build-api/package.json rename to api/package.json diff --git a/build-api/tsconfig.json b/api/tsconfig.json similarity index 100% rename from build-api/tsconfig.json rename to api/tsconfig.json diff --git a/build-api/tslint.json b/api/tslint.json similarity index 100% rename from build-api/tslint.json rename to api/tslint.json diff --git a/build-api/yarn.lock b/api/yarn.lock similarity index 100% rename from build-api/yarn.lock rename to api/yarn.lock diff --git a/build-wg/.gitignore b/build-wg/.gitignore deleted file mode 100644 index 77affc59..00000000 --- a/build-wg/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk -# DAppNodeSDK release directories -build_* diff --git a/docker-compose.yml b/docker-compose.yml index fa8e987d..af76c111 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.4" services: wireguard: - build: ./build-wg + build: . image: "wireguard.wireguard.dnp.dappnode.eth:0.1.0" restart: always cap_add: @@ -25,7 +25,7 @@ services: sysctls: - net.ipv4.conf.all.src_valid_mark=1 api: - build: ./build-api + build: ./api image: "api.wireguard.dnp.dappnode.eth:0.1.0" volumes: - "wg-config:/config" diff --git a/build-wg/package_versions.txt b/package_versions.txt similarity index 100% rename from build-wg/package_versions.txt rename to package_versions.txt diff --git a/build-wg/readme-vars.yml b/readme-vars.yml similarity index 100% rename from build-wg/readme-vars.yml rename to readme-vars.yml diff --git a/releases.json b/releases.json index 23f74339..dc4042e4 100644 --- a/releases.json +++ b/releases.json @@ -1,8 +1,8 @@ { "0.1.0": { - "hash": "/ipfs/QmcEcK8tEwYkeJWdvQaA6z5aaPdiJ23U6QtqTzzVoQEsJ2", + "hash": "/ipfs/QmWsXzsyLSfXznhppzKsC4Hq7t5J74M9ZAfqu1NxnxKo45", "uploadedTo": { - "dappnode": "Thu, 28 Jan 2021 02:25:25 GMT" + "dappnode": "Wed, 10 Mar 2021 10:15:26 GMT" } } } diff --git a/build-wg/root/app/add-peer b/root/app/add-peer similarity index 100% rename from build-wg/root/app/add-peer rename to root/app/add-peer diff --git a/build-wg/root/app/show-peer b/root/app/show-peer similarity index 100% rename from build-wg/root/app/show-peer rename to root/app/show-peer diff --git a/build-wg/root/defaults/Corefile b/root/defaults/Corefile similarity index 100% rename from build-wg/root/defaults/Corefile rename to root/defaults/Corefile diff --git a/build-wg/root/defaults/peer.conf b/root/defaults/peer.conf similarity index 100% rename from build-wg/root/defaults/peer.conf rename to root/defaults/peer.conf diff --git a/build-wg/root/defaults/server.conf b/root/defaults/server.conf similarity index 100% rename from build-wg/root/defaults/server.conf rename to root/defaults/server.conf diff --git a/build-wg/root/donate.txt b/root/donate.txt similarity index 100% rename from build-wg/root/donate.txt rename to root/donate.txt diff --git a/build-wg/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config similarity index 100% rename from build-wg/root/etc/cont-init.d/30-config rename to root/etc/cont-init.d/30-config diff --git a/build-wg/root/etc/services.d/coredns/run b/root/etc/services.d/coredns/run similarity index 100% rename from build-wg/root/etc/services.d/coredns/run rename to root/etc/services.d/coredns/run diff --git a/build-wg/root/etc/services.d/wireguard/run b/root/etc/services.d/wireguard/run similarity index 100% rename from build-wg/root/etc/services.d/wireguard/run rename to root/etc/services.d/wireguard/run From 2b528824f8cd8484c370c109d022b5f7c72cb932 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 11 Mar 2021 11:46:11 +0100 Subject: [PATCH 23/57] Converging changes --- .dockerignore | 2 -- Dockerfile | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index bb0698c1..8245cd53 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,4 @@ .gitattributes READMETEMPLATE.md README.md -root/app/node_modules -root/app/dist api \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 37f21dc5..3eba1e7b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,5 +61,6 @@ RUN \ # add local files COPY /root / + # ports and volumes EXPOSE 51820/udp From 6135a35197b372776c11cf626a668fda836eb0a6 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 11 Mar 2021 14:30:05 +0100 Subject: [PATCH 24/57] Old release --- releases.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/releases.json b/releases.json index dc4042e4..6e431fa0 100644 --- a/releases.json +++ b/releases.json @@ -1,8 +1,8 @@ { "0.1.0": { - "hash": "/ipfs/QmWsXzsyLSfXznhppzKsC4Hq7t5J74M9ZAfqu1NxnxKo45", + "hash": "/ipfs/QmcEcK8tEwYkeJWdvQaA6z5aaPdiJ23U6QtqTzzVoQEsJ2", "uploadedTo": { - "dappnode": "Wed, 10 Mar 2021 10:15:26 GMT" + "dappnode": "Thu, 28 Jan 2021 02:25:25 GMT" } } -} +} \ No newline at end of file From 10e0af12a30d7368cad6a8407480779d5a3339c3 Mon Sep 17 00:00:00 2001 From: pablo Date: Fri, 26 Mar 2021 12:45:49 +0100 Subject: [PATCH 25/57] compose migration --- docker-compose.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index af76c111..0a171128 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,10 +24,23 @@ services: - "51820:51820/udp" sysctls: - net.ipv4.conf.all.src_valid_mark=1 + networks: + dncore_network: + aliases: + - wireguard.wireguard.dappnode api: build: ./api image: "api.wireguard.dnp.dappnode.eth:0.1.0" volumes: - "wg-config:/config" + networks: + dncore_network: + aliases: + - api.wireguard.dappnode volumes: wg-config: {} + +networks: + dncore_network: + name: dncore_network + external: true From 9c200e235218fcb4f56d1295463aa8c1a23221c0 Mon Sep 17 00:00:00 2001 From: pablo Date: Fri, 26 Mar 2021 12:49:32 +0100 Subject: [PATCH 26/57] fix version --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0a171128..73abe49b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.4" +version: "3.5" services: wireguard: build: . From 306f4c7c192d0ad97b6daec12390146a8a0210f2 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Mon, 10 May 2021 22:52:30 +0200 Subject: [PATCH 27/57] Changing ymls and jsons --- dappnode_package.json | 4 ++-- docker-compose.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index 63d690a8..3e2544be 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -7,11 +7,11 @@ "categories": ["Developer tools"], "architectures": ["linux/amd64", "linux/arm64"], "links": { - "homepage": "https://github.com/Shard-Labs/docker-wireguard" + "homepage": "https://github.com/dappnode/DNP_WIREGUARD" }, "repository": { "type": "git", - "url": "https://github.com/Shard-Labs/docker-wireguard" + "url": "https://github.com/dappnode/DNP_WIREGUARD" }, "license": "GLP-3.0" } diff --git a/docker-compose.yml b/docker-compose.yml index af76c111..2306535b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,9 +14,9 @@ services: - PUID=1000 - PGID=1000 - SERVERPORT=51820 - - PEERDNS=172.33.1.2 + - PEERDNS=172.33.1.2,10.20.0.2 - INTERNAL_SUBNET=10.24.0.0 - - ALLOWEDIPS=172.33.0.0/16 + - ALLOWEDIPS=172.33.0.0/16,10.20.0.0/24 volumes: - "wg-config:/config" - "/lib/modules:/lib/modules" From d55c2644c1f72fa15a5ce6dd028a813f347ed304 Mon Sep 17 00:00:00 2001 From: pablo Date: Wed, 19 May 2021 13:08:50 +0200 Subject: [PATCH 28/57] Write two config files: remote and local todo serve both files in the API --- root/app/add-peer | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/root/app/add-peer b/root/app/add-peer index d2574a5e..cdc85244 100755 --- a/root/app/add-peer +++ b/root/app/add-peer @@ -7,11 +7,18 @@ if [ ! -f /config/wg0.conf ] || [ -z "$PEERS" ]; then exit 0 fi +# 1 argument: remote/local +function get_serverurl() { + if [ $1 === "remote" ]; then + SERVERURL=$(curl my.dappnode/global-envs/HOSTNAME) + elif [ $1 === "local" ]; then + SERVERURL=$(curl my.dappnode/global-envs/INTERNAL_IP) + fi +} + INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') -if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - SERVERURL=$(curl my.dappnode/global-envs/HOSTNAME) -fi + SERVERPORT=${SERVERPORT:-51820} if [ -z "$PEERDNS" ] || [ "$PEERDNS" = "auto" ]; then PEERDNS="${INTERFACE}.1" @@ -27,8 +34,16 @@ for i in {1..254}; do umask 077 wg genkey | tee /config/peer${i}/privatekey-peer${i} | wg pubkey > /config/peer${i}/publickey-peer${i} fi + # Remote peer + get_serverurl "remote" + eval "`printf %s` + cat < /config/peer${i}/peer${i}.remote.conf +`cat /config/templates/peer.conf` +DUDE" + # Local peer + get_serverurl "local" eval "`printf %s` - cat < /config/peer${i}/peer${i}.conf + cat < /config/peer${i}/peer${i}.local.conf `cat /config/templates/peer.conf` DUDE" cat <> /config/wg0.conf From ab6dd8bb0d12fb015e4b9bde13acae511e3febbf Mon Sep 17 00:00:00 2001 From: pablo Date: Wed, 19 May 2021 15:14:13 +0200 Subject: [PATCH 29/57] Added api for local file --- api/index.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/api/index.ts b/api/index.ts index a1b61444..aeb27816 100644 --- a/api/index.ts +++ b/api/index.ts @@ -8,17 +8,26 @@ const dataDir: string = process.env.DATA_DIR || "/config"; const app = express(); app.use(cors()); -app.get("/:device/:mode?", (req: express.Request, res: express.Response) => { +app.get("/:device/:remote/:mode?", (req: express.Request, res: express.Response) => { const { mode, device } = req.params; const fileExt = mode === "qr" ? "png" : "conf"; - const filePath = path.join( - dataDir, - `peer_${device}`, - `peer_${device}.${fileExt}` - ); + const remoteFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.remote.${fileExt}`); try { - res.status(200).sendFile(filePath); + res.status(200).sendFile(remoteFilePath); + } catch (e) { + if (e.code === "ENOENT") res.status(404).send("Not found"); + else res.status(500).send(e.stack); + } +}); + +app.get("/:device/:local/:mode?", (req: express.Request, res: express.Response) => { + const { mode, device } = req.params; + const fileExt = mode === "qr" ? "png" : "conf"; + const localFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.local.${fileExt}`); + + try { + res.status(200).sendFile(localFilePath); } catch (e) { if (e.code === "ENOENT") res.status(404).send("Not found"); else res.status(500).send(e.stack); From e7eb3c94c9b9bbaee4ecb1e7f572b6424411900f Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 20 May 2021 08:56:32 +0200 Subject: [PATCH 30/57] Create localConfigFile --- api/createLocalConfigFile.ts | 35 +++++++++++++++++++++++++++++++++++ api/index.ts | 10 ++++++---- api/tsconfig.json | 2 +- root/app/add-peer | 25 +++++-------------------- 4 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 api/createLocalConfigFile.ts diff --git a/api/createLocalConfigFile.ts b/api/createLocalConfigFile.ts new file mode 100644 index 00000000..78c5d2e9 --- /dev/null +++ b/api/createLocalConfigFile.ts @@ -0,0 +1,35 @@ +import fs from "fs"; + +// Params +const dappnodeApiInternalIp = "my.dappnode/global-envs/INTERNAL_IP"; +const serverPort = "51820"; + +export async function createLocalConfigFile(path: string): Promise { + try { + const localIp = await getLocalIp(); + const localEndpoint = `${localIp}:${serverPort}`; + + const remoteConfigFile = fs.readFileSync(path, "utf8"); + const localConfigFile = remoteConfigFile + .split("\n") + .map((row) => (row.startsWith("Endpoint =") ? (row = `Endpoint = ${localEndpoint}`) : row)) + .join("\n"); + + if (localConfigFile === remoteConfigFile) throw Error("Error generating localConfigFile"); + return localConfigFile; + } catch (e) { + throw Error(e); + } +} + +async function getLocalIp(): Promise { + try { + const response = await fetch(dappnodeApiInternalIp); + const localIp = response.text(); + if (!localIp) throw Error("localIp is empty"); + return localIp; + } catch (e) { + e.message = "Error fetching localIp" + e.message; + throw Error(e); + } +} diff --git a/api/index.ts b/api/index.ts index aeb27816..ef8ee00a 100644 --- a/api/index.ts +++ b/api/index.ts @@ -1,6 +1,7 @@ import express from "express"; import cors from "cors"; import path from "path"; +import { createLocalConfigFile } from "./createLocalConfigFile"; const port = process.env.SERVER_PORT || 80; const dataDir: string = process.env.DATA_DIR || "/config"; @@ -8,7 +9,7 @@ const dataDir: string = process.env.DATA_DIR || "/config"; const app = express(); app.use(cors()); -app.get("/:device/:remote/:mode?", (req: express.Request, res: express.Response) => { +app.get("/:device/remote/:mode?", (req: express.Request, res: express.Response) => { const { mode, device } = req.params; const fileExt = mode === "qr" ? "png" : "conf"; const remoteFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.remote.${fileExt}`); @@ -21,13 +22,14 @@ app.get("/:device/:remote/:mode?", (req: express.Request, res: express.Response) } }); -app.get("/:device/:local/:mode?", (req: express.Request, res: express.Response) => { +app.get("/:device/local/:mode?", async (req: express.Request, res: express.Response) => { const { mode, device } = req.params; const fileExt = mode === "qr" ? "png" : "conf"; - const localFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.local.${fileExt}`); + const remoteFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.local.${fileExt}`); + const localConfigFile = await createLocalConfigFile(remoteFilePath); try { - res.status(200).sendFile(localFilePath); + res.status(200).send(localConfigFile); } catch (e) { if (e.code === "ENOENT") res.status(404).send("Not found"); else res.status(500).send(e.stack); diff --git a/api/tsconfig.json b/api/tsconfig.json index 7a9cfd86..19c6b131 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -7,5 +7,5 @@ "strict": true, "outDir": "dist" }, - "include": ["./src", "index.ts"] + "include": ["./src", "index.ts", "createLocalConfigFile.ts"] } diff --git a/root/app/add-peer b/root/app/add-peer index cdc85244..e3e4b7c0 100755 --- a/root/app/add-peer +++ b/root/app/add-peer @@ -7,18 +7,11 @@ if [ ! -f /config/wg0.conf ] || [ -z "$PEERS" ]; then exit 0 fi -# 1 argument: remote/local -function get_serverurl() { - if [ $1 === "remote" ]; then - SERVERURL=$(curl my.dappnode/global-envs/HOSTNAME) - elif [ $1 === "local" ]; then - SERVERURL=$(curl my.dappnode/global-envs/INTERNAL_IP) - fi -} - INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') - +if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then + SERVERURL=$(curl my.dappnode/global-envs/HOSTNAME) +fi SERVERPORT=${SERVERPORT:-51820} if [ -z "$PEERDNS" ] || [ "$PEERDNS" = "auto" ]; then PEERDNS="${INTERFACE}.1" @@ -34,16 +27,8 @@ for i in {1..254}; do umask 077 wg genkey | tee /config/peer${i}/privatekey-peer${i} | wg pubkey > /config/peer${i}/publickey-peer${i} fi - # Remote peer - get_serverurl "remote" - eval "`printf %s` - cat < /config/peer${i}/peer${i}.remote.conf -`cat /config/templates/peer.conf` -DUDE" - # Local peer - get_serverurl "local" eval "`printf %s` - cat < /config/peer${i}/peer${i}.local.conf + cat < /config/peer${i}/peer${i}.conf `cat /config/templates/peer.conf` DUDE" cat <> /config/wg0.conf @@ -59,4 +44,4 @@ DUDE s6-svc -t /var/run/s6/services/wireguard break fi -done +done \ No newline at end of file From e2d06bcb4db3a47676a540510d6706272638f8db Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 20 May 2021 12:48:34 +0200 Subject: [PATCH 31/57] fix bug, added test --- api/createLocalConfigFile.ts | 31 +- api/package.json | 11 +- api/test/createLocalConfigFile.test.ts | 33 ++ api/tsconfig.json | 2 +- api/yarn.lock | 676 ++++++++++++++++++++++++- 5 files changed, 731 insertions(+), 22 deletions(-) create mode 100644 api/test/createLocalConfigFile.test.ts diff --git a/api/createLocalConfigFile.ts b/api/createLocalConfigFile.ts index 78c5d2e9..fb354b14 100644 --- a/api/createLocalConfigFile.ts +++ b/api/createLocalConfigFile.ts @@ -1,8 +1,10 @@ import fs from "fs"; +import got from "got"; +import ipRegex from "ip-regex"; // Params -const dappnodeApiInternalIp = "my.dappnode/global-envs/INTERNAL_IP"; -const serverPort = "51820"; +const dappnodeApiInternalIp = "http://my.dappnode/global-envs/INTERNAL_IP"; +const serverPort = 51820; export async function createLocalConfigFile(path: string): Promise { try { @@ -10,26 +12,33 @@ export async function createLocalConfigFile(path: string): Promise { const localEndpoint = `${localIp}:${serverPort}`; const remoteConfigFile = fs.readFileSync(path, "utf8"); - const localConfigFile = remoteConfigFile - .split("\n") - .map((row) => (row.startsWith("Endpoint =") ? (row = `Endpoint = ${localEndpoint}`) : row)) - .join("\n"); + const localConfigFile = setLocalEndpoint(remoteConfigFile, localEndpoint); if (localConfigFile === remoteConfigFile) throw Error("Error generating localConfigFile"); return localConfigFile; } catch (e) { - throw Error(e); + e.message = `Error creating : ${e.message}`; + throw e; } } +// Utils + async function getLocalIp(): Promise { try { - const response = await fetch(dappnodeApiInternalIp); - const localIp = response.text(); + const localIp = await got(dappnodeApiInternalIp).text(); if (!localIp) throw Error("localIp is empty"); + if (!ipRegex({ exact: true }).test(localIp)) throw Error("Invalida localIp"); return localIp; } catch (e) { - e.message = "Error fetching localIp" + e.message; - throw Error(e); + e.message = `Error fetching localIp: ${e.message}`; + throw e; } } + +export function setLocalEndpoint(configFile: string, localEndpoint: string): string { + return configFile + .split("\n") + .map((row) => (row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row)) + .join("\n"); +} diff --git a/api/package.json b/api/package.json index 7a893cf0..1259ff3b 100644 --- a/api/package.json +++ b/api/package.json @@ -5,6 +5,7 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { + "test": "mocha ./dist/test", "build": "tsc", "start": "node ./dist/server.js", "lint": "eslint . --ext .ts" @@ -13,15 +14,23 @@ "license": "MIT", "dependencies": { "cors": "^2.8.5", - "express": "^4.17.1" + "express": "^4.17.1", + "got": "^11.8.2", + "ip-regex": "^4.3.0" }, "devDependencies": { + "@types/chai": "^4.2.18", "@types/cors": "2.8.9", "@types/express": "^4.17.11", + "@types/got": "^9.6.11", + "@types/ip-regex": "^4.1.1", + "@types/mocha": "^8.2.2", "@types/node": "^14.14.21", "@typescript-eslint/eslint-plugin": "^4.6.1", "@typescript-eslint/parser": "^4.6.1", + "chai": "^4.3.4", "eslint": "^7.13.0", + "mocha": "^8.4.0", "typescript": "4.1.3" } } diff --git a/api/test/createLocalConfigFile.test.ts b/api/test/createLocalConfigFile.test.ts new file mode 100644 index 00000000..b09e8193 --- /dev/null +++ b/api/test/createLocalConfigFile.test.ts @@ -0,0 +1,33 @@ +import "mocha"; +import { expect } from "chai"; +import { setLocalEndpoint } from "../createLocalConfigFile"; + +describe("Config files", function () { + it("Create localConfig file from remoteConfigFile with local endpoint", function () { + const remoteConfig = `[Interface] +Address = AX032NVGI2RIB4 +PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= +ListenPort = 51820 +DNS = 172.33.1.2 + +[Peer] +PublicKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= +Endpoint = ff0239facf453517.dyndns.dappnode.io:51820 +AllowedIPs = 0.0.0.0/0`; + + const expextedLocalConfig = `[Interface] +Address = AX032NVGI2RIB4 +PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= +ListenPort = 51820 +DNS = 172.33.1.2 + +[Peer] +PublicKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= +Endpoint = 192.168.1.45:51820 +AllowedIPs = 0.0.0.0/0`; + + const localEndpoint = `192.168.1.45:51820`; + + expect(setLocalEndpoint(remoteConfig, localEndpoint)).to.deep.equal(expextedLocalConfig); + }); +}); diff --git a/api/tsconfig.json b/api/tsconfig.json index 19c6b131..ab5f8955 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -7,5 +7,5 @@ "strict": true, "outDir": "dist" }, - "include": ["./src", "index.ts", "createLocalConfigFile.ts"] + "include": ["./src", "index.ts", "createLocalConfigFile.ts", "test/*"] } diff --git a/api/yarn.lock b/api/yarn.lock index 47300b3d..904bf36a 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -60,6 +60,18 @@ "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" +"@sindresorhus/is@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.1.tgz#d26729db850fa327b7cacc5522252194404226f5" + integrity sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g== + +"@szmarczak/http-timer@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" + integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== + dependencies: + defer-to-connect "^2.0.0" + "@types/body-parser@*": version "1.19.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" @@ -68,6 +80,21 @@ "@types/connect" "*" "@types/node" "*" +"@types/cacheable-request@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" + integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "*" + "@types/node" "*" + "@types/responselike" "*" + +"@types/chai@^4.2.18": + version "4.2.18" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.18.tgz#0c8e298dbff8205e2266606c1ea5fbdba29b46e4" + integrity sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ== + "@types/connect@*": version "3.4.34" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901" @@ -99,16 +126,49 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/got@^9.6.11": + version "9.6.11" + resolved "https://registry.yarnpkg.com/@types/got/-/got-9.6.11.tgz#482b402cc5ee459481aeeadb08142ebb1a9afb26" + integrity sha512-dr3IiDNg5TDesGyuwTrN77E1Cd7DCdmCFtEfSGqr83jMMtcwhf/SGPbN2goY4JUWQfvxwY56+e5tjfi+oXeSdA== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + +"@types/http-cache-semantics@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" + integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== + +"@types/ip-regex@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@types/ip-regex/-/ip-regex-4.1.1.tgz#1afdee4731cb07bc7984a1669af19e02e536106e" + integrity sha512-RUEV39p+XoK1rO4nDQYXb1TATpyVKzfIr75HgR0074G/uA9RzjPsIK4TMlxh7KZ4WxcM512j03esP06tHMZNLA== + dependencies: + ip-regex "*" + "@types/json-schema@^7.0.3": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== +"@types/keyv@*": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" + integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== + dependencies: + "@types/node" "*" + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/mocha@^8.2.2": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0" + integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw== + "@types/node@*", "@types/node@^14.14.21": version "14.14.31" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055" @@ -124,6 +184,13 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== +"@types/responselike@*", "@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + "@types/serve-static@*": version "1.13.9" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" @@ -132,6 +199,11 @@ "@types/mime" "^1" "@types/node" "*" +"@types/tough-cookie@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d" + integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== + "@typescript-eslint/eslint-plugin@^4.6.1": version "4.15.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz#981b26b4076c62a5a55873fbef3fe98f83360c61" @@ -202,6 +274,11 @@ "@typescript-eslint/types" "4.15.2" eslint-visitor-keys "^2.0.0" +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -240,11 +317,16 @@ ajv@^7.0.2: require-from-string "^2.0.2" uri-js "^4.2.2" -ansi-colors@^4.1.1: +ansi-colors@4.1.1, ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" @@ -264,6 +346,14 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +anymatch@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -271,6 +361,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -281,16 +376,31 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -315,23 +425,63 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" + integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^2.0.0" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +chai@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -349,6 +499,42 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +chokidar@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -373,6 +559,13 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -424,18 +617,47 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@^4.0.1, debug@^4.1.1: +debug@4.3.1, debug@^4.0.1, debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -446,6 +668,11 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -475,6 +702,13 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + enquirer@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -482,11 +716,21 @@ enquirer@^2.3.5: dependencies: ansi-colors "^4.1.1" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -705,6 +949,14 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -713,11 +965,25 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -733,11 +999,33 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + glob-parent@^5.0.0, glob-parent@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" @@ -745,7 +1033,14 @@ glob-parent@^5.0.0, glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" -glob@^7.1.3: +glob-parent@~5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.6, glob@^7.1.3: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -776,6 +1071,28 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +got@^11.8.2: + version "11.8.2" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599" + integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.1" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -786,6 +1103,16 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + http-errors@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" @@ -808,6 +1135,14 @@ http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -856,22 +1191,39 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +ip-regex@*, ip-regex@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -883,6 +1235,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -893,6 +1250,13 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" + integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -901,6 +1265,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -916,6 +1285,13 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +keyv@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254" + integrity sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA== + dependencies: + json-buffer "3.0.1" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -924,11 +1300,30 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash@^4.17.15, lodash@^4.17.20: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -969,6 +1364,18 @@ mime-db@1.46.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== +mime-db@1.47.0: + version "1.47.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" + integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== + +mime-types@^2.1.12: + version "2.1.30" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" + integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== + dependencies: + mime-db "1.47.0" + mime-types@~2.1.24: version "2.1.29" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" @@ -981,13 +1388,54 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -minimatch@^3.0.4: +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" +mocha@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.4.0.tgz#677be88bf15980a3cae03a73e10a0fc3997f0cff" + integrity sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.1" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" + growl "1.10.5" + he "1.2.0" + js-yaml "4.0.0" + log-symbols "4.0.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.20" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1003,6 +1451,16 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.1.20: + version "3.1.20" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" + integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -1013,6 +1471,16 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + object-assign@^4: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -1025,7 +1493,7 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -1044,6 +1512,25 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -1056,6 +1543,11 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1076,6 +1568,16 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4: + version "2.2.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d" + integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg== + picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -1099,6 +1601,14 @@ proxy-addr@~2.0.5: forwarded "~0.1.2" ipaddr.js "1.9.1" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -1114,6 +1624,18 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.2.tgz#abf64491e6ecf0f38a6502403d4cda04f372dfd3" integrity sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg== +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -1129,21 +1651,45 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + regexpp@^3.0.0, regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +resolve-alpn@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.1.2.tgz#30b60cfbb0c0b8dc897940fe13fe255afcdd4d28" + integrity sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +responselike@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" + integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== + dependencies: + lowercase-keys "^2.0.0" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -1168,6 +1714,11 @@ safe-buffer@5.1.2: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -1199,6 +1750,13 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + serve-static@1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" @@ -1250,6 +1808,23 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" @@ -1259,6 +1834,13 @@ string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -1266,11 +1848,18 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1331,6 +1920,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -1376,24 +1970,88 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -which@^2.0.1: +which@2.0.2, which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +workerpool@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" + integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.7" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" + integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From abe87052ef44f855f34e8b5a25914ac85bb555f1 Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 20 May 2021 17:22:31 +0200 Subject: [PATCH 32/57] Modularized functions Todo: function to retrieve credentials using a command in the installer ? --- api/createLocalConfigFile.ts | 13 ++++++++++--- api/index.ts | 20 ++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/api/createLocalConfigFile.ts b/api/createLocalConfigFile.ts index fb354b14..6a4a40e2 100644 --- a/api/createLocalConfigFile.ts +++ b/api/createLocalConfigFile.ts @@ -1,23 +1,26 @@ import fs from "fs"; import got from "got"; import ipRegex from "ip-regex"; +import path from "path"; // Params const dappnodeApiInternalIp = "http://my.dappnode/global-envs/INTERNAL_IP"; const serverPort = 51820; +const dataDir: string = process.env.DATA_DIR || "/config"; -export async function createLocalConfigFile(path: string): Promise { +export async function createLocalConfigFile(device: string): Promise { try { + const remoteFilePath = getRemoteConfigFilePath(device, "conf"); const localIp = await getLocalIp(); const localEndpoint = `${localIp}:${serverPort}`; - const remoteConfigFile = fs.readFileSync(path, "utf8"); + const remoteConfigFile = fs.readFileSync(remoteFilePath, "utf8"); const localConfigFile = setLocalEndpoint(remoteConfigFile, localEndpoint); if (localConfigFile === remoteConfigFile) throw Error("Error generating localConfigFile"); return localConfigFile; } catch (e) { - e.message = `Error creating : ${e.message}`; + e.message = `Error creating localConfigFile: ${e.message}`; throw e; } } @@ -42,3 +45,7 @@ export function setLocalEndpoint(configFile: string, localEndpoint: string): str .map((row) => (row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row)) .join("\n"); } + +export function getRemoteConfigFilePath(device: string, mode: string): string { + return path.join(dataDir, `peer_${device}`, `peer_${device}.local.${mode}`); +} diff --git a/api/index.ts b/api/index.ts index ef8ee00a..ce6a4f70 100644 --- a/api/index.ts +++ b/api/index.ts @@ -1,20 +1,17 @@ import express from "express"; import cors from "cors"; -import path from "path"; -import { createLocalConfigFile } from "./createLocalConfigFile"; +import { createLocalConfigFile, getRemoteConfigFilePath } from "./createLocalConfigFile"; const port = process.env.SERVER_PORT || 80; -const dataDir: string = process.env.DATA_DIR || "/config"; const app = express(); app.use(cors()); app.get("/:device/remote/:mode?", (req: express.Request, res: express.Response) => { - const { mode, device } = req.params; - const fileExt = mode === "qr" ? "png" : "conf"; - const remoteFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.remote.${fileExt}`); - try { + const { mode, device } = req.params; + const fileExt = mode === "qr" ? "png" : "conf"; + const remoteFilePath = getRemoteConfigFilePath(device, fileExt); res.status(200).sendFile(remoteFilePath); } catch (e) { if (e.code === "ENOENT") res.status(404).send("Not found"); @@ -23,12 +20,11 @@ app.get("/:device/remote/:mode?", (req: express.Request, res: express.Response) }); app.get("/:device/local/:mode?", async (req: express.Request, res: express.Response) => { - const { mode, device } = req.params; - const fileExt = mode === "qr" ? "png" : "conf"; - const remoteFilePath = path.join(dataDir, `peer_${device}`, `peer_${device}.local.${fileExt}`); - const localConfigFile = await createLocalConfigFile(remoteFilePath); - try { + const { mode, device } = req.params; + if (mode === "qr") throw Error("qr mode not supported in local"); + + const localConfigFile = await createLocalConfigFile(device); res.status(200).send(localConfigFile); } catch (e) { if (e.code === "ENOENT") res.status(404).send("Not found"); From a865ce25f2d5ec898dd8976e6ab0070320c9a5b2 Mon Sep 17 00:00:00 2001 From: pablo Date: Fri, 21 May 2021 12:57:38 +0200 Subject: [PATCH 33/57] Added executables for qr wireguard remote and local credentials --- api/Dockerfile | 8 ++++- api/package.json | 4 ++- api/{ => src}/createLocalConfigFile.ts | 12 +++---- .../getWireguardCredentialsLocal.ts | 32 ++++++++++++++++++ .../getWireguardCredentialsRemote.ts | 33 +++++++++++++++++++ api/{ => src}/index.ts | 0 api/src/params.ts | 6 ++++ api/src/renderQrCode.ts | 8 +++++ api/test/createLocalConfigFile.test.ts | 2 +- api/tsconfig.json | 2 +- api/yarn.lock | 10 ++++++ 11 files changed, 105 insertions(+), 12 deletions(-) rename api/{ => src}/createLocalConfigFile.ts (77%) create mode 100644 api/src/executables/getWireguardCredentialsLocal.ts create mode 100644 api/src/executables/getWireguardCredentialsRemote.ts rename api/{ => src}/index.ts (100%) create mode 100644 api/src/params.ts create mode 100644 api/src/renderQrCode.ts diff --git a/api/Dockerfile b/api/Dockerfile index 8a1f9b68..e2b921ca 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -16,4 +16,10 @@ RUN apk add --update --no-cache nodejs COPY --from=builder /app/dist/ ./ COPY --from=builder /app/node_modules/ ./node_modules -ENTRYPOINT [ "node", "index" ] +# Prepare external executables +RUN chmod +x /app/src/executables/getWireguardCredentialsLocal.js && \ + chmod +x /app/src/executables/getWireguardCredentialsRemote.js && \ + ln -s /app/src/executables/getWireguardCredentialsLocal.js /usr/local/bin/getWireguardCredentialsLocal && \ + ln -s /app/src/executables/getWireguardCredentialsRemote.js /usr/local/bin/getWireguardCredentialsRemote + +ENTRYPOINT [ "node", "src/index" ] diff --git a/api/package.json b/api/package.json index 1259ff3b..6cdf7f30 100644 --- a/api/package.json +++ b/api/package.json @@ -16,7 +16,8 @@ "cors": "^2.8.5", "express": "^4.17.1", "got": "^11.8.2", - "ip-regex": "^4.3.0" + "ip-regex": "^4.3.0", + "qrcode-terminal": "^0.12.0" }, "devDependencies": { "@types/chai": "^4.2.18", @@ -26,6 +27,7 @@ "@types/ip-regex": "^4.1.1", "@types/mocha": "^8.2.2", "@types/node": "^14.14.21", + "@types/qrcode-terminal": "^0.12.0", "@typescript-eslint/eslint-plugin": "^4.6.1", "@typescript-eslint/parser": "^4.6.1", "chai": "^4.3.4", diff --git a/api/createLocalConfigFile.ts b/api/src/createLocalConfigFile.ts similarity index 77% rename from api/createLocalConfigFile.ts rename to api/src/createLocalConfigFile.ts index 6a4a40e2..74692626 100644 --- a/api/createLocalConfigFile.ts +++ b/api/src/createLocalConfigFile.ts @@ -2,17 +2,13 @@ import fs from "fs"; import got from "got"; import ipRegex from "ip-regex"; import path from "path"; - -// Params -const dappnodeApiInternalIp = "http://my.dappnode/global-envs/INTERNAL_IP"; -const serverPort = 51820; -const dataDir: string = process.env.DATA_DIR || "/config"; +import { params } from "./params"; export async function createLocalConfigFile(device: string): Promise { try { const remoteFilePath = getRemoteConfigFilePath(device, "conf"); const localIp = await getLocalIp(); - const localEndpoint = `${localIp}:${serverPort}`; + const localEndpoint = `${localIp}:${params.SERVER_PORT}`; const remoteConfigFile = fs.readFileSync(remoteFilePath, "utf8"); const localConfigFile = setLocalEndpoint(remoteConfigFile, localEndpoint); @@ -29,7 +25,7 @@ export async function createLocalConfigFile(device: string): Promise { async function getLocalIp(): Promise { try { - const localIp = await got(dappnodeApiInternalIp).text(); + const localIp = await got(params.DAPPNODE_INTERNAL_IP).text(); if (!localIp) throw Error("localIp is empty"); if (!ipRegex({ exact: true }).test(localIp)) throw Error("Invalida localIp"); return localIp; @@ -47,5 +43,5 @@ export function setLocalEndpoint(configFile: string, localEndpoint: string): str } export function getRemoteConfigFilePath(device: string, mode: string): string { - return path.join(dataDir, `peer_${device}`, `peer_${device}.local.${mode}`); + return path.join(params.DATA_DIR, `peer_${device}`, `peer_${device}.local.${mode}`); } diff --git a/api/src/executables/getWireguardCredentialsLocal.ts b/api/src/executables/getWireguardCredentialsLocal.ts new file mode 100644 index 00000000..4b460163 --- /dev/null +++ b/api/src/executables/getWireguardCredentialsLocal.ts @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +// This script must return the MASTER_ADMIN credentials formated +// as a nice message in the terminal + a QR code +// +// It will be run as a separate process, maybe in a different container + +import { renderQrCode } from "../renderQrCode"; +import { params } from "../params"; +import { createLocalConfigFile } from "../createLocalConfigFile"; + +// If user does CTRL + C, exit process +process.on("SIGINT", () => process.exit(128)); + +(async function (): Promise { + try { + console.log( + `Fetching local Wireguard credentials. It may take some time; use CTRL + C to stop`, + ); + + const wireguardLocalCredentials = await createLocalConfigFile(params.MASTER_ADMIN); + + // If rendering the QR fails, show the error and continue, the raw URL is consumable + console.log(` + +${await renderQrCode(wireguardLocalCredentials).catch((e) => e.stack)}`); + } catch (e) { + // Exit process cleanly to prevent showing 'Unhandled rejection' + console.error(e); + process.exit(1); + } +})(); diff --git a/api/src/executables/getWireguardCredentialsRemote.ts b/api/src/executables/getWireguardCredentialsRemote.ts new file mode 100644 index 00000000..ac360631 --- /dev/null +++ b/api/src/executables/getWireguardCredentialsRemote.ts @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +// This script must return the MASTER_ADMIN credentials formated +// as a nice message in the terminal + a QR code +// +// It will be run as a separate process, maybe in a different container + +import { renderQrCode } from "../renderQrCode"; +import { params } from "../params"; +import { getRemoteConfigFilePath } from "../createLocalConfigFile"; +import fs from "fs"; + +// If user does CTRL + C, exit process +process.on("SIGINT", () => process.exit(128)); + +(async function (): Promise { + try { + console.log( + `Fetching remote Wireguard credentials. It may take some time; use CTRL + C to stop`, + ); + const remoteFilePath = getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"); + const wireguardRemoteCredentials = fs.readFileSync(remoteFilePath, "utf-8"); + + // If rendering the QR fails, show the error and continue, the raw URL is consumable + console.log(` + +${await renderQrCode(wireguardRemoteCredentials).catch((e) => e.stack)}`); + } catch (e) { + // Exit process cleanly to prevent showing 'Unhandled rejection' + console.error(e); + process.exit(1); + } +})(); diff --git a/api/index.ts b/api/src/index.ts similarity index 100% rename from api/index.ts rename to api/src/index.ts diff --git a/api/src/params.ts b/api/src/params.ts new file mode 100644 index 00000000..fdc95648 --- /dev/null +++ b/api/src/params.ts @@ -0,0 +1,6 @@ +export const params = { + MASTER_ADMIN: "dappnode_admin", + DAPPNODE_INTERNAL_IP: "http://my.dappnode/global-envs/INTERNAL_IP", + SERVER_PORT: 51820, + DATA_DIR: process.env.DATA_DIR || "/config", +}; diff --git a/api/src/renderQrCode.ts b/api/src/renderQrCode.ts new file mode 100644 index 00000000..a99e8d5b --- /dev/null +++ b/api/src/renderQrCode.ts @@ -0,0 +1,8 @@ +import qrcode from "qrcode-terminal"; + +export function renderQrCode(data: string): Promise { + return new Promise((resolve) => { + qrcode.setErrorLevel("L"); + qrcode.generate(data, { small: false }, resolve); + }); +} diff --git a/api/test/createLocalConfigFile.test.ts b/api/test/createLocalConfigFile.test.ts index b09e8193..82ca376e 100644 --- a/api/test/createLocalConfigFile.test.ts +++ b/api/test/createLocalConfigFile.test.ts @@ -1,6 +1,6 @@ import "mocha"; import { expect } from "chai"; -import { setLocalEndpoint } from "../createLocalConfigFile"; +import { setLocalEndpoint } from "../src/createLocalConfigFile"; describe("Config files", function () { it("Create localConfig file from remoteConfigFile with local endpoint", function () { diff --git a/api/tsconfig.json b/api/tsconfig.json index ab5f8955..6f6294cb 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -7,5 +7,5 @@ "strict": true, "outDir": "dist" }, - "include": ["./src", "index.ts", "createLocalConfigFile.ts", "test/*"] + "include": ["src/**/*", "test/*"] } diff --git a/api/yarn.lock b/api/yarn.lock index 904bf36a..8d87f620 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -174,6 +174,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055" integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g== +"@types/qrcode-terminal@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#cee13a96db9346e3240e2128290465db56799961" + integrity sha512-g0fQKl3IVnUePV8tLkiBTduxAVSZsXts444T2aMfjOEGxd7XoeSIs16/AmRe2NlcJLqbvsOBSXov7dKSo4wigA== + "@types/qs@*": version "6.9.5" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" @@ -1614,6 +1619,11 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +qrcode-terminal@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" + integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" From 9e9d8275d4f1c45169df710e89c4dac6545002ff Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 27 May 2021 08:39:01 +0200 Subject: [PATCH 34/57] Update getWireguardCredentialsLocal.ts --- .../getWireguardCredentialsLocal.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/api/src/executables/getWireguardCredentialsLocal.ts b/api/src/executables/getWireguardCredentialsLocal.ts index 4b460163..5cc00c2e 100644 --- a/api/src/executables/getWireguardCredentialsLocal.ts +++ b/api/src/executables/getWireguardCredentialsLocal.ts @@ -9,21 +9,21 @@ import { renderQrCode } from "../renderQrCode"; import { params } from "../params"; import { createLocalConfigFile } from "../createLocalConfigFile"; -// If user does CTRL + C, exit process -process.on("SIGINT", () => process.exit(128)); - (async function (): Promise { try { console.log( - `Fetching local Wireguard credentials. It may take some time; use CTRL + C to stop`, + `Preparing local Wireguard credentials; use CTRL + C to stop`, ); - const wireguardLocalCredentials = await createLocalConfigFile(params.MASTER_ADMIN); - - // If rendering the QR fails, show the error and continue, the raw URL is consumable - console.log(` + const config = await createLocalConfigFile(params.MASTER_ADMIN); + + // If rendering the QR fails, show error and the raw config + const qrStr = await renderQrCode(config).catch(e => { + console.error("Error rendering QR code", e) + return config + }) -${await renderQrCode(wireguardLocalCredentials).catch((e) => e.stack)}`); + console.log(`\n\n${qrStr}`); } catch (e) { // Exit process cleanly to prevent showing 'Unhandled rejection' console.error(e); From 4125651fcc43061fda73b4050456bd7add32e840 Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 27 May 2021 08:40:48 +0200 Subject: [PATCH 35/57] Update getWireguardCredentialsRemote.ts --- .../getWireguardCredentialsRemote.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/api/src/executables/getWireguardCredentialsRemote.ts b/api/src/executables/getWireguardCredentialsRemote.ts index ac360631..13dac6dc 100644 --- a/api/src/executables/getWireguardCredentialsRemote.ts +++ b/api/src/executables/getWireguardCredentialsRemote.ts @@ -10,21 +10,22 @@ import { params } from "../params"; import { getRemoteConfigFilePath } from "../createLocalConfigFile"; import fs from "fs"; -// If user does CTRL + C, exit process -process.on("SIGINT", () => process.exit(128)); - (async function (): Promise { try { console.log( - `Fetching remote Wireguard credentials. It may take some time; use CTRL + C to stop`, + `Preparing remote Wireguard credentials; use CTRL + C to stop`, ); + const remoteFilePath = getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"); - const wireguardRemoteCredentials = fs.readFileSync(remoteFilePath, "utf-8"); + const config = fs.readFileSync(remoteFilePath, "utf-8"); - // If rendering the QR fails, show the error and continue, the raw URL is consumable - console.log(` + // If rendering the QR fails, show error and the raw config + const qrStr = await renderQrCode(config).catch(e => { + console.error("Error rendering QR code", e); + return config; + }) -${await renderQrCode(wireguardRemoteCredentials).catch((e) => e.stack)}`); + console.log(`\n\n${qrStr}`); } catch (e) { // Exit process cleanly to prevent showing 'Unhandled rejection' console.error(e); From c8bc5bceee30c4b8f4a715c442d7f1684e7092bd Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 27 May 2021 12:39:30 +0200 Subject: [PATCH 36/57] added cli --- api/Dockerfile | 6 +- .../executables/getWireguardCredentials.ts | 114 ++++++++++++++++++ api/src/params.ts | 3 + 3 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 api/src/executables/getWireguardCredentials.ts diff --git a/api/Dockerfile b/api/Dockerfile index e2b921ca..93aaceee 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -17,9 +17,7 @@ COPY --from=builder /app/dist/ ./ COPY --from=builder /app/node_modules/ ./node_modules # Prepare external executables -RUN chmod +x /app/src/executables/getWireguardCredentialsLocal.js && \ - chmod +x /app/src/executables/getWireguardCredentialsRemote.js && \ - ln -s /app/src/executables/getWireguardCredentialsLocal.js /usr/local/bin/getWireguardCredentialsLocal && \ - ln -s /app/src/executables/getWireguardCredentialsRemote.js /usr/local/bin/getWireguardCredentialsRemote +RUN chmod +x /app/src/executables/getWireguardCredentials.js && \ + ln -s /app/src/executables/getWireguardCredentials.js /usr/local/bin/getWireguardCredentials ENTRYPOINT [ "node", "src/index" ] diff --git a/api/src/executables/getWireguardCredentials.ts b/api/src/executables/getWireguardCredentials.ts new file mode 100644 index 00000000..479d11e6 --- /dev/null +++ b/api/src/executables/getWireguardCredentials.ts @@ -0,0 +1,114 @@ +#!/usr/bin/env node + +// This script must return the MASTER_ADMIN credentials formated +// as a nice message in the terminal + a QR code +// +// It will be run as a separate process, maybe in a different container + +import { renderQrCode } from "../renderQrCode"; +import { params } from "../params"; +import { + createLocalConfigFile, + getRemoteConfigFilePath, +} from "../createLocalConfigFile"; +import fs from "fs"; + +(async function (): Promise { + try { + // getWireguardCredentials --local => return wireguard local credentials in plain text + // getWireguardCredentials --local --qr => return wireguard local credentials in qr format + + const args = process.argv; + if ( + args.length > 2 || + (args.length > 0 && !args.includes("local" || "qr" || "help")) + ) + throw Error(params.ERROR_MESSAGE); + + // getWireguardCredentials => return wireguard remote credentials in plain text + if (args.length === 0) { + console.log(createStartingLog("remote", "text")); + console.log(await getCredentials("remote", "text")); + } + + switch (args[0]) { + // getWireguardCredentials --qr => return wireguard remote credentials in qr format + case "--qr": + if (args[1] === "local") { + console.log(createStartingLog("local", "qr")); + console.log(await getCredentials("local", "qr")); + return; + } else if (!args[1]) { + console.log(createStartingLog("remote", "qr")); + console.log(await getCredentials("remote", "qr")); + return; + } + throw Error(params.ERROR_MESSAGE); + + case "--local": + if (args[1] === "qr") { + console.log(createStartingLog("local", "qr")); + console.log(await getCredentials("local", "qr")); + return; + } else if (!args[1]) { + console.log(createStartingLog("local", "text")); + console.log(await getCredentials("local", "text")); + return; + } + throw Error(params.ERROR_MESSAGE); + + case "--help": + console.log(params.HELP_MESSAGE); + default: + throw Error(params.ERROR_MESSAGE); + } + } catch (e) { + // Exit process cleanly to prevent showing 'Unhandled rejection' + console.error(e); + process.exit(1); + } +})(); + +// Utils +function createStartingLog( + credentials: "local" | "remote", + mode: "qr" | "text" +): string { + return `Preparing ${credentials} ${mode} Wireguard credentials; use CTRL + C to stop`; +} + +async function getCredentials( + credentials: "local" | "remote", + mode: "qr" | "text" +) { + switch (credentials) { + case "local": + const localTextCreds = await createLocalConfigFile(params.MASTER_ADMIN); + if (mode === "qr") return localTextCreds; + + // If rendering the QR fails, show error and the raw config + const localQrCreds = await renderQrCode(localTextCreds).catch((e) => { + console.error("Error rendering local QR code", e); + return localTextCreds; + }); + + return localQrCreds; + + case "remote": + const remoteFilePath = getRemoteConfigFilePath( + params.MASTER_ADMIN, + "conf" + ); + const remoteTextCreds = fs.readFileSync(remoteFilePath, "utf-8"); + + if (mode === "text") return remoteTextCreds; + + // If rendering the QR fails, show error and the raw remoteTextCreds + const remoteQrCreds = await renderQrCode(remoteTextCreds).catch((e) => { + console.error("Error rendering remote QR code", e); + return remoteTextCreds; + }); + + return remoteQrCreds; + } +} diff --git a/api/src/params.ts b/api/src/params.ts index fdc95648..32f9f10a 100644 --- a/api/src/params.ts +++ b/api/src/params.ts @@ -3,4 +3,7 @@ export const params = { DAPPNODE_INTERNAL_IP: "http://my.dappnode/global-envs/INTERNAL_IP", SERVER_PORT: 51820, DATA_DIR: process.env.DATA_DIR || "/config", + HELP_MESSAGE: + "Get your wireguard credentials. Command: dappnode_wireguard\n\n--qr => will return credentials in QR format. Default are plain text\n--local => return local credentials to solve NAT loopback issues. Default are remote credentials\n--help => print out this message", + ERROR_MESSAGE: "Arguments not supported, run dappnode_wireguard --help", }; From 065d4a820323ceafa45aca9f0c62db20057e212c Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 27 May 2021 13:02:14 +0200 Subject: [PATCH 37/57] Removed unusued files, edited env name --- api/src/createLocalConfigFile.ts | 2 +- .../getWireguardCredentialsLocal.ts | 32 ----------------- .../getWireguardCredentialsRemote.ts | 34 ------------------- api/src/params.ts | 3 +- 4 files changed, 3 insertions(+), 68 deletions(-) delete mode 100644 api/src/executables/getWireguardCredentialsLocal.ts delete mode 100644 api/src/executables/getWireguardCredentialsRemote.ts diff --git a/api/src/createLocalConfigFile.ts b/api/src/createLocalConfigFile.ts index 74692626..9597e445 100644 --- a/api/src/createLocalConfigFile.ts +++ b/api/src/createLocalConfigFile.ts @@ -25,7 +25,7 @@ export async function createLocalConfigFile(device: string): Promise { async function getLocalIp(): Promise { try { - const localIp = await got(params.DAPPNODE_INTERNAL_IP).text(); + const localIp = await got(params.DAPPNODE_API_URL_GET_INTERNAL_IP).text(); if (!localIp) throw Error("localIp is empty"); if (!ipRegex({ exact: true }).test(localIp)) throw Error("Invalida localIp"); return localIp; diff --git a/api/src/executables/getWireguardCredentialsLocal.ts b/api/src/executables/getWireguardCredentialsLocal.ts deleted file mode 100644 index 5cc00c2e..00000000 --- a/api/src/executables/getWireguardCredentialsLocal.ts +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env node - -// This script must return the MASTER_ADMIN credentials formated -// as a nice message in the terminal + a QR code -// -// It will be run as a separate process, maybe in a different container - -import { renderQrCode } from "../renderQrCode"; -import { params } from "../params"; -import { createLocalConfigFile } from "../createLocalConfigFile"; - -(async function (): Promise { - try { - console.log( - `Preparing local Wireguard credentials; use CTRL + C to stop`, - ); - - const config = await createLocalConfigFile(params.MASTER_ADMIN); - - // If rendering the QR fails, show error and the raw config - const qrStr = await renderQrCode(config).catch(e => { - console.error("Error rendering QR code", e) - return config - }) - - console.log(`\n\n${qrStr}`); - } catch (e) { - // Exit process cleanly to prevent showing 'Unhandled rejection' - console.error(e); - process.exit(1); - } -})(); diff --git a/api/src/executables/getWireguardCredentialsRemote.ts b/api/src/executables/getWireguardCredentialsRemote.ts deleted file mode 100644 index 13dac6dc..00000000 --- a/api/src/executables/getWireguardCredentialsRemote.ts +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env node - -// This script must return the MASTER_ADMIN credentials formated -// as a nice message in the terminal + a QR code -// -// It will be run as a separate process, maybe in a different container - -import { renderQrCode } from "../renderQrCode"; -import { params } from "../params"; -import { getRemoteConfigFilePath } from "../createLocalConfigFile"; -import fs from "fs"; - -(async function (): Promise { - try { - console.log( - `Preparing remote Wireguard credentials; use CTRL + C to stop`, - ); - - const remoteFilePath = getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"); - const config = fs.readFileSync(remoteFilePath, "utf-8"); - - // If rendering the QR fails, show error and the raw config - const qrStr = await renderQrCode(config).catch(e => { - console.error("Error rendering QR code", e); - return config; - }) - - console.log(`\n\n${qrStr}`); - } catch (e) { - // Exit process cleanly to prevent showing 'Unhandled rejection' - console.error(e); - process.exit(1); - } -})(); diff --git a/api/src/params.ts b/api/src/params.ts index 32f9f10a..307f9621 100644 --- a/api/src/params.ts +++ b/api/src/params.ts @@ -1,6 +1,7 @@ export const params = { MASTER_ADMIN: "dappnode_admin", - DAPPNODE_INTERNAL_IP: "http://my.dappnode/global-envs/INTERNAL_IP", + DAPPNODE_API_URL_GET_INTERNAL_IP: + "http://my.dappnode/global-envs/INTERNAL_IP", SERVER_PORT: 51820, DATA_DIR: process.env.DATA_DIR || "/config", HELP_MESSAGE: From 04aa143cda128b7f5646b9295436ed14f2420936 Mon Sep 17 00:00:00 2001 From: pablo Date: Thu, 27 May 2021 14:32:32 +0200 Subject: [PATCH 38/57] Simplified cli --- .../executables/getWireguardCredentials.ts | 115 +++++------------- api/src/params.ts | 4 +- 2 files changed, 34 insertions(+), 85 deletions(-) diff --git a/api/src/executables/getWireguardCredentials.ts b/api/src/executables/getWireguardCredentials.ts index 479d11e6..06b88781 100644 --- a/api/src/executables/getWireguardCredentials.ts +++ b/api/src/executables/getWireguardCredentials.ts @@ -7,61 +7,22 @@ import { renderQrCode } from "../renderQrCode"; import { params } from "../params"; -import { - createLocalConfigFile, - getRemoteConfigFilePath, -} from "../createLocalConfigFile"; +import { createLocalConfigFile, getRemoteConfigFilePath } from "../createLocalConfigFile"; import fs from "fs"; (async function (): Promise { try { - // getWireguardCredentials --local => return wireguard local credentials in plain text - // getWireguardCredentials --local --qr => return wireguard local credentials in qr format - - const args = process.argv; - if ( - args.length > 2 || - (args.length > 0 && !args.includes("local" || "qr" || "help")) - ) - throw Error(params.ERROR_MESSAGE); - - // getWireguardCredentials => return wireguard remote credentials in plain text - if (args.length === 0) { - console.log(createStartingLog("remote", "text")); - console.log(await getCredentials("remote", "text")); + // Help message + if (process.argv.includes("--help")) { + console.log(params.HELP_MESSAGE); + return; } - switch (args[0]) { - // getWireguardCredentials --qr => return wireguard remote credentials in qr format - case "--qr": - if (args[1] === "local") { - console.log(createStartingLog("local", "qr")); - console.log(await getCredentials("local", "qr")); - return; - } else if (!args[1]) { - console.log(createStartingLog("remote", "qr")); - console.log(await getCredentials("remote", "qr")); - return; - } - throw Error(params.ERROR_MESSAGE); + const isQr = process.argv.includes("--qr"); + const isLocal = process.argv.includes("--local"); - case "--local": - if (args[1] === "qr") { - console.log(createStartingLog("local", "qr")); - console.log(await getCredentials("local", "qr")); - return; - } else if (!args[1]) { - console.log(createStartingLog("local", "text")); - console.log(await getCredentials("local", "text")); - return; - } - throw Error(params.ERROR_MESSAGE); - - case "--help": - console.log(params.HELP_MESSAGE); - default: - throw Error(params.ERROR_MESSAGE); - } + console.log(createStartingLog(isLocal ? "local" : "remote", isQr ? "qr" : "text")); + console.log(await getCredentials(isLocal, isQr)); } catch (e) { // Exit process cleanly to prevent showing 'Unhandled rejection' console.error(e); @@ -70,45 +31,35 @@ import fs from "fs"; })(); // Utils -function createStartingLog( - credentials: "local" | "remote", - mode: "qr" | "text" -): string { +function createStartingLog(credentials: "local" | "remote", mode: "qr" | "text"): string { return `Preparing ${credentials} ${mode} Wireguard credentials; use CTRL + C to stop`; } -async function getCredentials( - credentials: "local" | "remote", - mode: "qr" | "text" -) { - switch (credentials) { - case "local": - const localTextCreds = await createLocalConfigFile(params.MASTER_ADMIN); - if (mode === "qr") return localTextCreds; - - // If rendering the QR fails, show error and the raw config - const localQrCreds = await renderQrCode(localTextCreds).catch((e) => { - console.error("Error rendering local QR code", e); - return localTextCreds; - }); - - return localQrCreds; +async function getCredentials(isLocal: boolean, isQr: boolean) { + // LOCAL + if (isLocal) { + const localTextCreds = await createLocalConfigFile(params.MASTER_ADMIN); + if (!isQr) return localTextCreds; + // If rendering the QR fails, show error and the raw config + const localQrCreds = await renderQrCode(localTextCreds).catch((e) => { + console.error("Error rendering local QR code", e); + return localTextCreds; + }); + + return localQrCreds; + } - case "remote": - const remoteFilePath = getRemoteConfigFilePath( - params.MASTER_ADMIN, - "conf" - ); - const remoteTextCreds = fs.readFileSync(remoteFilePath, "utf-8"); + //REMOTE + const remoteFilePath = getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"); + const remoteTextCreds = fs.readFileSync(remoteFilePath, "utf-8"); - if (mode === "text") return remoteTextCreds; + if (!isQr) return remoteTextCreds; - // If rendering the QR fails, show error and the raw remoteTextCreds - const remoteQrCreds = await renderQrCode(remoteTextCreds).catch((e) => { - console.error("Error rendering remote QR code", e); - return remoteTextCreds; - }); + // If rendering the QR fails, show error and the raw remoteTextCreds + const remoteQrCreds = await renderQrCode(remoteTextCreds).catch((e) => { + console.error("Error rendering remote QR code", e); + return remoteTextCreds; + }); - return remoteQrCreds; - } + return remoteQrCreds; } diff --git a/api/src/params.ts b/api/src/params.ts index 307f9621..7dc0264e 100644 --- a/api/src/params.ts +++ b/api/src/params.ts @@ -1,10 +1,8 @@ export const params = { MASTER_ADMIN: "dappnode_admin", - DAPPNODE_API_URL_GET_INTERNAL_IP: - "http://my.dappnode/global-envs/INTERNAL_IP", + DAPPNODE_API_URL_GET_INTERNAL_IP: "http://my.dappnode/global-envs/INTERNAL_IP", SERVER_PORT: 51820, DATA_DIR: process.env.DATA_DIR || "/config", HELP_MESSAGE: "Get your wireguard credentials. Command: dappnode_wireguard\n\n--qr => will return credentials in QR format. Default are plain text\n--local => return local credentials to solve NAT loopback issues. Default are remote credentials\n--help => print out this message", - ERROR_MESSAGE: "Arguments not supported, run dappnode_wireguard --help", }; From fc822a69a7c31da3dbb7023b073ac7531a6d49aa Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 27 May 2021 15:50:41 +0200 Subject: [PATCH 39/57] Simplify more --- .../executables/getWireguardCredentials.ts | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/api/src/executables/getWireguardCredentials.ts b/api/src/executables/getWireguardCredentials.ts index 06b88781..6638f621 100644 --- a/api/src/executables/getWireguardCredentials.ts +++ b/api/src/executables/getWireguardCredentials.ts @@ -7,7 +7,10 @@ import { renderQrCode } from "../renderQrCode"; import { params } from "../params"; -import { createLocalConfigFile, getRemoteConfigFilePath } from "../createLocalConfigFile"; +import { + createLocalConfigFile, + getRemoteConfigFilePath, +} from "../createLocalConfigFile"; import fs from "fs"; (async function (): Promise { @@ -21,45 +24,31 @@ import fs from "fs"; const isQr = process.argv.includes("--qr"); const isLocal = process.argv.includes("--local"); - console.log(createStartingLog(isLocal ? "local" : "remote", isQr ? "qr" : "text")); - console.log(await getCredentials(isLocal, isQr)); + const configName = isLocal ? "local" : "remote"; + const configFormat = isQr ? "qr" : "text"; + console.log( + `Preparing ${configName} ${configFormat} Wireguard credentials; use CTRL + C to stop` + ); + + const config = isLocal + ? await createLocalConfigFile(params.MASTER_ADMIN) + : fs.readFileSync( + getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"), + "utf-8" + ); + + const str = isQr + ? // If rendering the QR fails, show error and the raw remoteTextCreds + await renderQrCode(config).catch((e) => { + console.error("Error rendering remote QR code", e); + return config; + }) + : config; + + console.log(str); } catch (e) { // Exit process cleanly to prevent showing 'Unhandled rejection' console.error(e); process.exit(1); } })(); - -// Utils -function createStartingLog(credentials: "local" | "remote", mode: "qr" | "text"): string { - return `Preparing ${credentials} ${mode} Wireguard credentials; use CTRL + C to stop`; -} - -async function getCredentials(isLocal: boolean, isQr: boolean) { - // LOCAL - if (isLocal) { - const localTextCreds = await createLocalConfigFile(params.MASTER_ADMIN); - if (!isQr) return localTextCreds; - // If rendering the QR fails, show error and the raw config - const localQrCreds = await renderQrCode(localTextCreds).catch((e) => { - console.error("Error rendering local QR code", e); - return localTextCreds; - }); - - return localQrCreds; - } - - //REMOTE - const remoteFilePath = getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"); - const remoteTextCreds = fs.readFileSync(remoteFilePath, "utf-8"); - - if (!isQr) return remoteTextCreds; - - // If rendering the QR fails, show error and the raw remoteTextCreds - const remoteQrCreds = await renderQrCode(remoteTextCreds).catch((e) => { - console.error("Error rendering remote QR code", e); - return remoteTextCreds; - }); - - return remoteQrCreds; -} From 7047047234031c41baa24ac641b17fa11e231bc6 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 27 May 2021 15:52:34 +0200 Subject: [PATCH 40/57] Add padding --- api/src/executables/getWireguardCredentials.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/executables/getWireguardCredentials.ts b/api/src/executables/getWireguardCredentials.ts index 6638f621..eb5cd472 100644 --- a/api/src/executables/getWireguardCredentials.ts +++ b/api/src/executables/getWireguardCredentials.ts @@ -45,7 +45,7 @@ import fs from "fs"; }) : config; - console.log(str); + console.log(`\n\n${str}\n\n`); } catch (e) { // Exit process cleanly to prevent showing 'Unhandled rejection' console.error(e); From 3aae142bf9cab48520c670703fc16f9dfe32cce0 Mon Sep 17 00:00:00 2001 From: pablo Date: Fri, 28 May 2021 01:32:20 +0200 Subject: [PATCH 41/57] Be consistent with container name --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 8ceee9fc..ed7bd45e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: wireguard: build: . image: "wireguard.wireguard.dnp.dappnode.eth:0.1.0" + container_name: "DAppNodeCore-wireguard.wireguard.dnp.dappnode.eth" restart: always cap_add: - NET_ADMIN @@ -31,6 +32,7 @@ services: api: build: ./api image: "api.wireguard.dnp.dappnode.eth:0.1.0" + container_name: "DAppNodeCore-api.wireguard.dnp.dappnode.eth" volumes: - "wg-config:/config" networks: From f5d580a4aa42a669aed16de01412d8bf818bbf71 Mon Sep 17 00:00:00 2001 From: pablo Date: Fri, 28 May 2021 09:10:16 +0200 Subject: [PATCH 42/57] fix api bug --- api/src/createLocalConfigFile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/createLocalConfigFile.ts b/api/src/createLocalConfigFile.ts index 9597e445..ab7eebe9 100644 --- a/api/src/createLocalConfigFile.ts +++ b/api/src/createLocalConfigFile.ts @@ -43,5 +43,5 @@ export function setLocalEndpoint(configFile: string, localEndpoint: string): str } export function getRemoteConfigFilePath(device: string, mode: string): string { - return path.join(params.DATA_DIR, `peer_${device}`, `peer_${device}.local.${mode}`); + return path.join(params.DATA_DIR, `peer_${device}`, `peer_${device}.${mode}`); } From aae5eced741b63f70d2983f4792a2e8fd176007b Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 3 Jun 2021 10:19:14 +0200 Subject: [PATCH 43/57] Remove sysctls --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ed7bd45e..c5c1ac32 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,8 +23,6 @@ services: - "/lib/modules:/lib/modules" ports: - "51820:51820/udp" - sysctls: - - net.ipv4.conf.all.src_valid_mark=1 networks: dncore_network: aliases: From 3b3abc8a0ffed14d5487b71677feac77db202666 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 3 Jun 2021 12:14:02 +0200 Subject: [PATCH 44/57] Simplify route --- api/src/index.ts | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/api/src/index.ts b/api/src/index.ts index ce6a4f70..9e24ac3d 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -1,37 +1,47 @@ -import express from "express"; +import express, { ErrorRequestHandler } from "express"; import cors from "cors"; -import { createLocalConfigFile, getRemoteConfigFilePath } from "./createLocalConfigFile"; +import { + createLocalConfigFile, + getRemoteConfigFilePath, +} from "./createLocalConfigFile"; const port = process.env.SERVER_PORT || 80; const app = express(); app.use(cors()); -app.get("/:device/remote/:mode?", (req: express.Request, res: express.Response) => { +// - remote: '/dappnode_admin' +// - remote qr: '/dappnode_admin?qr' +// - local: '/dappnode_admin?local' +// - local qr: '/dappnode_admin?local&qr' +app.get("/:device", async (req: express.Request, res: express.Response) => { try { - const { mode, device } = req.params; - const fileExt = mode === "qr" ? "png" : "conf"; - const remoteFilePath = getRemoteConfigFilePath(device, fileExt); - res.status(200).sendFile(remoteFilePath); - } catch (e) { - if (e.code === "ENOENT") res.status(404).send("Not found"); - else res.status(500).send(e.stack); - } -}); - -app.get("/:device/local/:mode?", async (req: express.Request, res: express.Response) => { - try { - const { mode, device } = req.params; - if (mode === "qr") throw Error("qr mode not supported in local"); + const { device } = req.params; + // Allow to send `?local` without setting to `?local=1` + const local = Boolean(req.query.local) || req.query.local === ""; + const qr = Boolean(req.query.qr) || req.query.qr === ""; - const localConfigFile = await createLocalConfigFile(device); - res.status(200).send(localConfigFile); + if (local) { + if (qr) throw Error("qr mode not supported in local"); + const localConfigFile = await createLocalConfigFile(device); + res.status(200).send(localConfigFile); + } else { + const fileExt = qr ? "png" : "conf"; + const remoteFilePath = getRemoteConfigFilePath(device, fileExt); + res.status(200).sendFile(remoteFilePath); + } } catch (e) { if (e.code === "ENOENT") res.status(404).send("Not found"); else res.status(500).send(e.stack); } }); +// Return JSON instead of HTML +const errorJsonHandler: ErrorRequestHandler = async (err, req, res, next) => { + res.status(500).send(err); +}; +app.use(errorJsonHandler); + const server = app.listen(port, () => console.log(`Listening on port ${port}`)); process.on("SIGTERM", shutdown); From cddd71d7b24eeeeb9a5d5e7c925dda7121df98c9 Mon Sep 17 00:00:00 2001 From: pablo Date: Fri, 11 Jun 2021 11:27:13 +0200 Subject: [PATCH 45/57] add restart policies --- docker-compose.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ed7bd45e..9d19acc2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,8 +3,8 @@ services: wireguard: build: . image: "wireguard.wireguard.dnp.dappnode.eth:0.1.0" - container_name: "DAppNodeCore-wireguard.wireguard.dnp.dappnode.eth" - restart: always + container_name: DAppNodeCore-wireguard.wireguard.dnp.dappnode.eth + restart: unless-stopped cap_add: - NET_ADMIN - SYS_MODULE @@ -15,9 +15,9 @@ services: - PUID=1000 - PGID=1000 - SERVERPORT=51820 - - PEERDNS=172.33.1.2,10.20.0.2 + - "PEERDNS=172.33.1.2,10.20.0.2" - INTERNAL_SUBNET=10.24.0.0 - - ALLOWEDIPS=172.33.0.0/16,10.20.0.0/24 + - "ALLOWEDIPS=172.33.0.0/16,10.20.0.0/24" volumes: - "wg-config:/config" - "/lib/modules:/lib/modules" @@ -31,8 +31,9 @@ services: - wireguard.wireguard.dappnode api: build: ./api + restart: unless-stopped image: "api.wireguard.dnp.dappnode.eth:0.1.0" - container_name: "DAppNodeCore-api.wireguard.dnp.dappnode.eth" + container_name: DAppNodeCore-api.wireguard.dnp.dappnode.eth volumes: - "wg-config:/config" networks: @@ -41,7 +42,6 @@ services: - api.wireguard.dappnode volumes: wg-config: {} - networks: dncore_network: name: dncore_network From 2a07596f8043db2b4602e9b91ba7a028e733d4ea Mon Sep 17 00:00:00 2001 From: pablo Date: Mon, 14 Jun 2021 11:26:08 +0200 Subject: [PATCH 46/57] Modified order --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index caa854ad..a36dda46 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,9 +29,9 @@ services: - wireguard.wireguard.dappnode api: build: ./api - restart: unless-stopped image: "api.wireguard.dnp.dappnode.eth:0.1.0" container_name: DAppNodeCore-api.wireguard.dnp.dappnode.eth + restart: unless-stopped volumes: - "wg-config:/config" networks: From 052ccff8564821a726c1690175238354d997d17c Mon Sep 17 00:00:00 2001 From: pablo Date: Mon, 23 Aug 2021 17:14:07 +0200 Subject: [PATCH 47/57] increase delay from 40s to 3 mins --- dappnode_package.json | 2 +- docker-compose.yml | 4 ++-- root/etc/cont-init.d/30-config | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index 3e2544be..b2518840 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -1,6 +1,6 @@ { "name": "wireguard.dnp.dappnode.eth", - "version": "0.1.0", + "version": "0.1.1", "description": "Wireguard for DAppNode", "type": "dncore", "author": "Shardlabs", diff --git a/docker-compose.yml b/docker-compose.yml index a36dda46..965e815e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.5" services: wireguard: build: . - image: "wireguard.wireguard.dnp.dappnode.eth:0.1.0" + image: "wireguard.wireguard.dnp.dappnode.eth:0.1.1" container_name: DAppNodeCore-wireguard.wireguard.dnp.dappnode.eth restart: unless-stopped cap_add: @@ -29,7 +29,7 @@ services: - wireguard.wireguard.dappnode api: build: ./api - image: "api.wireguard.dnp.dappnode.eth:0.1.0" + image: "api.wireguard.dnp.dappnode.eth:0.1.1" container_name: DAppNodeCore-api.wireguard.dnp.dappnode.eth restart: unless-stopped volumes: diff --git a/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config index 5eeb3a14..6743c019 100644 --- a/root/etc/cont-init.d/30-config +++ b/root/etc/cont-init.d/30-config @@ -244,7 +244,7 @@ if [ -n "$PEERS" ]; then fi PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - for i in {1..20}; do + for i in {1..90}; do echo "**** Fetching DAppNode domain..." SERVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) if [ ! -z $SERVERURL ]; then break; fi From 709591add1a683ecf0d4217ad2e118256268c7f7 Mon Sep 17 00:00:00 2001 From: pablo Date: Tue, 24 Aug 2021 11:27:40 +0200 Subject: [PATCH 48/57] exit if empty --- root/etc/cont-init.d/30-config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config index 6743c019..5c8937a5 100644 --- a/root/etc/cont-init.d/30-config +++ b/root/etc/cont-init.d/30-config @@ -254,6 +254,10 @@ if [ -n "$PEERS" ]; then else echo "**** External server address is set to $SERVERURL ****" fi + + # Exit if SERVERURL not set + [ -z "$SERVERURL" ] && { echo "**** ERROR: External server address not found at my.dappnode/global-envs/HOSTNAME ****"; exit 1} + SERVERPORT=${SERVERPORT:-51820} echo "**** External server port is set to ${SERVERPORT}. Make sure that port is properly forwarded to port 51820 inside this container ****" INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} From 8cad3b784c2b567bc6cc6b31b592a47206dcc9bd Mon Sep 17 00:00:00 2001 From: pablo Date: Mon, 30 Aug 2021 11:23:00 +0200 Subject: [PATCH 49/57] remove exit --- root/etc/cont-init.d/30-config | 3 --- 1 file changed, 3 deletions(-) diff --git a/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config index 5c8937a5..0173eee3 100644 --- a/root/etc/cont-init.d/30-config +++ b/root/etc/cont-init.d/30-config @@ -255,9 +255,6 @@ if [ -n "$PEERS" ]; then echo "**** External server address is set to $SERVERURL ****" fi - # Exit if SERVERURL not set - [ -z "$SERVERURL" ] && { echo "**** ERROR: External server address not found at my.dappnode/global-envs/HOSTNAME ****"; exit 1} - SERVERPORT=${SERVERPORT:-51820} echo "**** External server port is set to ${SERVERPORT}. Make sure that port is properly forwarded to port 51820 inside this container ****" INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} From 44e19d1ce7e4b89a391a20ca0d4e8e664376089e Mon Sep 17 00:00:00 2001 From: Alex Peterson Date: Sun, 27 Feb 2022 20:35:20 -0600 Subject: [PATCH 50/57] fix license typo, fix broken links fixed the license type typo, and added the report/issues link which is broken in the current version, and fixed the git URL to be the git file with the `.git` extension as used in all other manifests. --- dappnode_package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index b2518840..bf00ea35 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -9,9 +9,12 @@ "links": { "homepage": "https://github.com/dappnode/DNP_WIREGUARD" }, + "bugs": { + "url": "https://github.com/dappnode/DNP_WIREGUARD/issues" + }, "repository": { "type": "git", - "url": "https://github.com/dappnode/DNP_WIREGUARD" + "url": "https://github.com/dappnode/DNP_WIREGUARD.git" }, - "license": "GLP-3.0" + "license": "GPL-3.0" } From 9efceb23e1b37ef9e8899cae594facb41df9904e Mon Sep 17 00:00:00 2001 From: pablo Date: Tue, 22 Mar 2022 14:16:17 +0100 Subject: [PATCH 51/57] add PR template --- .github/PULL_REQUEST_TEMPLATE.md | 53 ++++++++++---------------------- 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f50314f1..129db85f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,43 +1,22 @@ - + -[linuxserverurl]: https://linuxserver.io -[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] +**What type of PR is this?** +> Uncomment one line below and remove others. +> +> Bug fix +> Feature +> Documentation +> Other - +**What does this PR do? Why is it needed?** - - - - - +**How can be tested?** +> Provide well detailed instructions to test this PR - - - - - - ------------------------------- - - - [ ] I have read the [contributing](https://github.com/linuxserver/docker-wireguard/blob/master/.github/CONTRIBUTING.md) guideline and understand that I have made the correct modifications - ------------------------------- - - - -## Description: - - -## Benefits of this PR and context: - - -## How Has This Been Tested? - - - - - -## Source / References: - +**Other notes for review** From 96b8ffb5388cc9ffe6f9a54aecff8f2304677ac1 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 22 Sep 2022 16:35:57 +0200 Subject: [PATCH 52/57] Bump --- Dockerfile | 2 +- Dockerfile.aarch64 | 2 +- Dockerfile.armhf | 2 +- root/defaults/server.conf | 4 ++-- root/etc/cont-init.d/30-config | 22 +++++++++++----------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3eba1e7b..7273fc73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:bionic +FROM ghcr.io/linuxserver/baseimage-ubuntu:focal # set version label ARG BUILD_DATE diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index 7d2fab1f..18628487 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,4 +1,4 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:arm64v8-bionic +FROM ghcr.io/linuxserver/baseimage-ubuntu:arm64v8-focal # set version label ARG BUILD_DATE diff --git a/Dockerfile.armhf b/Dockerfile.armhf index 40a482a2..6cf259e3 100644 --- a/Dockerfile.armhf +++ b/Dockerfile.armhf @@ -1,4 +1,4 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:arm32v7-bionic +FROM ghcr.io/linuxserver/baseimage-ubuntu:arm32v7-focal # set version label ARG BUILD_DATE diff --git a/root/defaults/server.conf b/root/defaults/server.conf index 9255d385..757682d6 100644 --- a/root/defaults/server.conf +++ b/root/defaults/server.conf @@ -2,5 +2,5 @@ Address = ${INTERFACE}.1 ListenPort = 51820 PrivateKey = $(cat /config/server/privatekey-server) -PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE +PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE +PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE diff --git a/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config index 0173eee3..79307f47 100644 --- a/root/etc/cont-init.d/30-config +++ b/root/etc/cont-init.d/30-config @@ -10,7 +10,7 @@ if ip link add dev test type wireguard; then SKIP_COMPILE="true" ip link del dev test else - echo "**** The wireguard module is not active, will attempt kernel header install and module compilation. ****" + echo "**** The wireguard module is not active, will attempt kernel header install and module compilation. If you believe that your kernel should have wireguard support already, make sure that it is activated via modprobe! ****" fi # install headers if necessary @@ -30,31 +30,31 @@ if [ "$SKIP_COMPILE" != "true" ] && [ ! -e /lib/modules/$(uname -r)/build ]; the apt-get install -y \ raspberrypi-kernel-headers elif uname -v | grep -q 'Ubuntu'; then - echo "**** Ubuntu kernel detected, but likely not Bionic. ****" - echo "**** Attempting to install kernel headers from Ubuntu Xenial repo ****" + echo "**** Ubuntu kernel detected, but likely not Focal. ****" + echo "**** Attempting to install kernel headers from Ubuntu Bionic repo ****" if uname -m | grep -q 'x86_64'; then echo -e \ - "deb http://archive.ubuntu.com/ubuntu/ xenial main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted" \ - > /etc/apt/sources.list.d/xenial-focal.list + "deb http://archive.ubuntu.com/ubuntu/ bionic main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted" \ + > /etc/apt/sources.list.d/xenial-bionic.list else echo -e \ - "deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted\n\ndeb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted" \ - > /etc/apt/sources.list.d/xenial-focal.list + "deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\n\ndeb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted" \ + > /etc/apt/sources.list.d/xenial-bionic.list fi apt-get update if apt-cache show linux-headers-$(uname -r) 2&>1 >/dev/null; then apt-get install -y \ linux-headers-$(uname -r) else - echo "**** No kernel headers found in the Ubuntu Xenial repo!! Trying Ubuntu Focal. ****" - sed -i 's/xenial/focal/g' /etc/apt/sources.list.d/xenial-focal.list + echo "**** No kernel headers found in the Ubuntu Bionic repo!! Trying Ubuntu Xenial. ****" + sed -i 's/bionic/xenial/g' /etc/apt/sources.list.d/xenial-bionic.list apt-get update if apt-cache show linux-headers-$(uname -r) 2&>1 >/dev/null; then apt-get install -y \ linux-headers-$(uname -r) else echo "**** No kernel headers found in the Ubuntu repos!! Will try the headers from host (if mapped), may or may not work ****" - rm -rf /etc/apt/sources.list.d/xenial-focal.list + rm -rf /etc/apt/sources.list.d/xenial-bionic.list fi fi elif uname -v | grep -q 'Debian'; then @@ -156,7 +156,7 @@ DUDE sleep infinity fi else - echo "**** Kernel headers don't seem to be available, can't compile the module. Sleeping now. . . ****" + echo "**** Kernel headers don't seem to be available in Ubuntu, Debian and Raspbian repos, or shared from the host; therefore can't compile the module. Sleeping now. . . ****" sleep infinity fi fi From 64dad162ce6368eca1ac9ade4e5b29fd6427b0f5 Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Fri, 4 Nov 2022 19:48:38 +0100 Subject: [PATCH 53/57] Create CODEOWNERS --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..7e0d66f0 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @dappnode/core From 6db2cd0c723b2929e1cb575d3681d7c9a04eb50d Mon Sep 17 00:00:00 2001 From: dsimog01 <47595345+dsimog01@users.noreply.github.com> Date: Fri, 28 Jul 2023 17:58:50 +0200 Subject: [PATCH 54/57] Improve resilience (#32) * Adding aliases to improve code resiliance (#31) * Adding more aliases to improve code resiliance * Removed hardcoded dappmanager IP * Improve getLocalIp * Add log for retrieving domain * Improve iteration * Add retries for internal IP retrieval * Add dappmanager IP as fallback --------- Co-authored-by: Alex Gonzalez Matias <104903362+alexgonmad@users.noreply.github.com> --- api/src/createLocalConfigFile.ts | 58 +++++++++++++++++++++++++------- api/src/params.ts | 3 +- releases.json | 2 +- root/app/add-peer | 26 ++++++++++++-- root/etc/cont-init.d/30-config | 31 +++++++++++++---- 5 files changed, 96 insertions(+), 24 deletions(-) diff --git a/api/src/createLocalConfigFile.ts b/api/src/createLocalConfigFile.ts index ab7eebe9..91247048 100644 --- a/api/src/createLocalConfigFile.ts +++ b/api/src/createLocalConfigFile.ts @@ -7,13 +7,14 @@ import { params } from "./params"; export async function createLocalConfigFile(device: string): Promise { try { const remoteFilePath = getRemoteConfigFilePath(device, "conf"); - const localIp = await getLocalIp(); + const localIp = await getLocalIpWithRetries(30); const localEndpoint = `${localIp}:${params.SERVER_PORT}`; const remoteConfigFile = fs.readFileSync(remoteFilePath, "utf8"); const localConfigFile = setLocalEndpoint(remoteConfigFile, localEndpoint); - if (localConfigFile === remoteConfigFile) throw Error("Error generating localConfigFile"); + if (localConfigFile === remoteConfigFile) + throw Error("Error generating localConfigFile"); return localConfigFile; } catch (e) { e.message = `Error creating localConfigFile: ${e.message}`; @@ -23,22 +24,55 @@ export async function createLocalConfigFile(device: string): Promise { // Utils +async function getLocalIpWithRetries(retries: number): Promise { + // An integer n >= 1 + retries = Math.max(Math.floor(retries), 1); + + for (let i = 0; i < retries - 1; i++) { + try { + return await getLocalIp(); + } catch (e) { + console.log(`Error getting local IP: ${e.message}`); + console.log(`Retrying... (${i + 1}/${retries})`); + } + } + + return await getLocalIp(); +} + async function getLocalIp(): Promise { - try { - const localIp = await got(params.DAPPNODE_API_URL_GET_INTERNAL_IP).text(); - if (!localIp) throw Error("localIp is empty"); - if (!ipRegex({ exact: true }).test(localIp)) throw Error("Invalida localIp"); - return localIp; - } catch (e) { - e.message = `Error fetching localIp: ${e.message}`; - throw e; + const dappmanagerHostnames = params.DAPPMANAGER_HOSTNAMES; + const getLocalIpUrls = dappmanagerHostnames.map( + (hostname) => `http://${hostname}${params.GET_INTERNAL_IP_ENDPOINT}` + ); + + let errorMessages: string[] = []; + + for (const url of getLocalIpUrls) { + try { + const localIp = await got(url).text(); + if (!localIp) throw Error("Local IP is empty"); + if (!ipRegex({ exact: true }).test(localIp)) + throw Error("Invalid local IP"); + return localIp; + } catch (e) { + errorMessages.push( + `Local IP could not be fetched from ${url}: ${e.message}` + ); + } } + throw Error(errorMessages.join("\n")); } -export function setLocalEndpoint(configFile: string, localEndpoint: string): string { +export function setLocalEndpoint( + configFile: string, + localEndpoint: string +): string { return configFile .split("\n") - .map((row) => (row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row)) + .map((row) => + row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row + ) .join("\n"); } diff --git a/api/src/params.ts b/api/src/params.ts index 7dc0264e..d28278eb 100644 --- a/api/src/params.ts +++ b/api/src/params.ts @@ -1,6 +1,7 @@ export const params = { MASTER_ADMIN: "dappnode_admin", - DAPPNODE_API_URL_GET_INTERNAL_IP: "http://my.dappnode/global-envs/INTERNAL_IP", + DAPPMANAGER_HOSTNAMES: ["my.dappnode", "dappmanager.dappnode", "172.33.1.7"], // TODO: Remove dappmanager IP when IP migration is performed + GET_INTERNAL_IP_ENDPOINT: "/global-envs/INTERNAL_IP", SERVER_PORT: 51820, DATA_DIR: process.env.DATA_DIR || "/config", HELP_MESSAGE: diff --git a/releases.json b/releases.json index 6e431fa0..23f74339 100644 --- a/releases.json +++ b/releases.json @@ -5,4 +5,4 @@ "dappnode": "Thu, 28 Jan 2021 02:25:25 GMT" } } -} \ No newline at end of file +} diff --git a/root/app/add-peer b/root/app/add-peer index e3e4b7c0..672d7926 100755 --- a/root/app/add-peer +++ b/root/app/add-peer @@ -9,14 +9,34 @@ fi INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') -if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - SERVERURL=$(curl my.dappnode/global-envs/HOSTNAME) -fi SERVERPORT=${SERVERPORT:-51820} + if [ -z "$PEERDNS" ] || [ "$PEERDNS" = "auto" ]; then PEERDNS="${INTERFACE}.1" fi +if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then + + function fetchDappnodeDomain { + for i in {1..10}; do + for domain in "$@"; do + echo "**** Fetching DAppNode domain from $domain..." + SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") + if [ ! -z "$SERVERURL" ]; then + break + fi + sleep 2 + done + done + } + + # TODO: Remove IP when the IP migration is performed + domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7") + + fetchDappnodeDomain "${domains[@]}" + +fi + for i in {1..254}; do if grep -q "AllowedIPs = ${INTERFACE}.$(( $i + 1 ))/32" /config/wg0.conf; then echo "Peer $i exists" diff --git a/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config index 79307f47..4b87f6c2 100644 --- a/root/etc/cont-init.d/30-config +++ b/root/etc/cont-init.d/30-config @@ -244,13 +244,30 @@ if [ -n "$PEERS" ]; then fi PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - for i in {1..90}; do - echo "**** Fetching DAppNode domain..." - SERVERURL=$(curl -s my.dappnode/global-envs/HOSTNAME) - if [ ! -z $SERVERURL ]; then break; fi - sleep 2 - done - echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" + + function fetchDappnodeDomain { + for i in {1..30}; do + for domain in "$@"; do + echo "**** Fetching DAppNode domain from $domain..." + SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") + if [ ! -z "$SERVERURL" ]; then + break 2 + fi + sleep 2 + done + done + } + + # TODO: Remove IP when the IP migration is performed + domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7") + + fetchDappnodeDomain "${domains[@]}" + + if [ -z "$SERVERURL" ]; then + echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" + else + echo "**** SERVERURL var is set to $SERVERURL ****" + fi else echo "**** External server address is set to $SERVERURL ****" fi From 284f91a5de3852315fdb51c2854105b031628899 Mon Sep 17 00:00:00 2001 From: dappnodedev <144998261+dappnodedev@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:59:53 +0100 Subject: [PATCH 55/57] Add HOSTNAME global env (#35) * Add HOSTNAME global env * Add logs --- dappnode_package.json | 8 ++- root/app/add-peer | 43 +++++++------ root/etc/cont-init.d/30-config | 112 +++++++++++++++++---------------- 3 files changed, 90 insertions(+), 73 deletions(-) diff --git a/dappnode_package.json b/dappnode_package.json index bf00ea35..e24c3b91 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -16,5 +16,11 @@ "type": "git", "url": "https://github.com/dappnode/DNP_WIREGUARD.git" }, - "license": "GPL-3.0" + "license": "GPL-3.0", + "globalEnvs": [ + { + "envs": ["HOSTNAME"], + "services": ["wireguard"] + } + ] } diff --git a/root/app/add-peer b/root/app/add-peer index 672d7926..ed33bde9 100755 --- a/root/app/add-peer +++ b/root/app/add-peer @@ -17,51 +17,56 @@ fi if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - function fetchDappnodeDomain { - for i in {1..10}; do + # If _DAPPNODE_GLOBAL_HOSTNAME is set, use it as SERVERURL + if [ ! -z "$_DAPPNODE_GLOBAL_HOSTNAME" ]; then + echo "**** _DAPPNODE_GLOBAL_HOSTNAME is set, using it as SERVERURL ****" + SERVERURL="$_DAPPNODE_GLOBAL_HOSTNAME" + else + function fetchDappnodeDomain { + for i in {1..10}; do for domain in "$@"; do echo "**** Fetching DAppNode domain from $domain..." SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") - if [ ! -z "$SERVERURL" ]; then - break - fi + if [ ! -z "$SERVERURL" ]; then + break + fi sleep 2 done - done - } + done + } - # TODO: Remove IP when the IP migration is performed - domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7") + domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7" "10.20.0.7") - fetchDappnodeDomain "${domains[@]}" + fetchDappnodeDomain "${domains[@]}" + fi fi for i in {1..254}; do - if grep -q "AllowedIPs = ${INTERFACE}.$(( $i + 1 ))/32" /config/wg0.conf; then + if grep -q "AllowedIPs = ${INTERFACE}.$(($i + 1))/32" /config/wg0.conf; then echo "Peer $i exists" else echo "Adding new Peer $i" mkdir -p /config/peer${i} if [ ! -f /config/peer${i}/privatekey-peer${i} ]; then umask 077 - wg genkey | tee /config/peer${i}/privatekey-peer${i} | wg pubkey > /config/peer${i}/publickey-peer${i} + wg genkey | tee /config/peer${i}/privatekey-peer${i} | wg pubkey >/config/peer${i}/publickey-peer${i} fi - eval "`printf %s` + eval "$(printf %s) cat < /config/peer${i}/peer${i}.conf -`cat /config/templates/peer.conf` +$(cat /config/templates/peer.conf) DUDE" - cat <> /config/wg0.conf + cat <>/config/wg0.conf [Peer] PublicKey = $(cat /config/peer${i}/publickey-peer${i}) -AllowedIPs = ${INTERFACE}.$(( $i + 1 ))/32 +AllowedIPs = ${INTERFACE}.$(($i + 1))/32 DUDE echo "PEER ${i} QR code:" - qrencode -t ansiutf8 < /config/peer${i}/peer${i}.conf - qrencode -o /config/peer${i}/peer${i}.png < /config/peer${i}/peer${i}.conf + qrencode -t ansiutf8 1 >/dev/null; then + if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then apt-get install -y \ linux-headers-$(uname -r) elif (uname -r | grep -q 'v7+') || (uname -r | grep -q 'v7l+') || (uname -r | grep -q 'v8+'); then @@ -25,7 +25,7 @@ if [ "$SKIP_COMPILE" != "true" ] && [ ! -e /lib/modules/$(uname -r)/build ]; the curl -s http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - echo -e \ "deb http://archive.raspberrypi.org/debian/ buster main\ndeb-src http://archive.raspberrypi.org/debian/ buster main" \ - > /etc/apt/sources.list.d/raspbian.list + >/etc/apt/sources.list.d/raspbian.list apt-get update apt-get install -y \ raspberrypi-kernel-headers @@ -35,21 +35,21 @@ if [ "$SKIP_COMPILE" != "true" ] && [ ! -e /lib/modules/$(uname -r)/build ]; the if uname -m | grep -q 'x86_64'; then echo -e \ "deb http://archive.ubuntu.com/ubuntu/ bionic main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted" \ - > /etc/apt/sources.list.d/xenial-bionic.list + >/etc/apt/sources.list.d/xenial-bionic.list else echo -e \ - "deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\n\ndeb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted" \ - > /etc/apt/sources.list.d/xenial-bionic.list + "deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\n\ndeb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted" \ + >/etc/apt/sources.list.d/xenial-bionic.list fi apt-get update - if apt-cache show linux-headers-$(uname -r) 2&>1 >/dev/null; then + if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then apt-get install -y \ linux-headers-$(uname -r) else echo "**** No kernel headers found in the Ubuntu Bionic repo!! Trying Ubuntu Xenial. ****" sed -i 's/bionic/xenial/g' /etc/apt/sources.list.d/xenial-bionic.list apt-get update - if apt-cache show linux-headers-$(uname -r) 2&>1 >/dev/null; then + if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then apt-get install -y \ linux-headers-$(uname -r) else @@ -61,7 +61,7 @@ if [ "$SKIP_COMPILE" != "true" ] && [ ! -e /lib/modules/$(uname -r)/build ]; the echo "**** Debian host detected, attempting to install kernel headers from Debian Buster repo ****" curl -s https://ftp-master.debian.org/keys/archive-key-10.asc | apt-key add - curl -s https://ftp-master.debian.org/keys/archive-key-10-security.asc | apt-key add - - cat < /etc/apt/sources.list.d/debian.list + cat </etc/apt/sources.list.d/debian.list deb http://deb.debian.org/debian buster main contrib non-free deb-src http://deb.debian.org/debian buster main contrib non-free deb http://deb.debian.org/debian-security/ buster/updates main contrib non-free @@ -72,7 +72,7 @@ deb http://deb.debian.org/debian buster-backports main contrib non-free deb-src http://deb.debian.org/debian buster-backports main contrib non-free DUDE apt-get update - if apt-cache show linux-headers-$(uname -r) 2&>1 >/dev/null; then + if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then if uname -r | grep -qs "bpo"; then echo "**** Backported kernel detected ****" apt-get install -y -t buster-backports \ @@ -87,7 +87,7 @@ DUDE curl -s https://ftp-master.debian.org/keys/archive-key-9-security.asc | apt-key add - sed -i 's/buster/stretch/g' /etc/apt/sources.list.d/debian.list apt-get update - if apt-cache show linux-headers-$(uname -r) 2&>1 >/dev/null; then + if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then if uname -r | grep -qs "bpo"; then echo "**** Backported kernel detected ****" apt-get install -y -t stretch-backports \ @@ -107,12 +107,12 @@ DUDE fi if [ "$SKIP_COMPILE" != "true" ]; then - if [ -e /lib/modules/$(uname -r)/build ]; then + if [ -e /lib/modules/$(uname -r)/build ]; then echo "**** Kernel headers seem to be present, attempting to build the wireguard module. . . ****" if [ ! -f /lib/modules/$(uname -r)/build/certs/signing_key.pem ]; then mkdir -p /lib/modules/$(uname -r)/build/certs cd /lib/modules/$(uname -r)/build/certs - cat <> x509.genkey + cat <>x509.genkey [ req ] default_bits = 4096 distinguished_name = req_distinguished_name @@ -133,18 +133,18 @@ DUDE openssl req -new -nodes -utf8 -sha512 -days 36500 -batch -x509 -config x509.genkey -outform DER -out signing_key.x509 -keyout signing_key.pem fi cd /app - for release in "" "v1.0.20200520" "v1.0.20200330" "v0.0.20200105"; do + for release in "" "v1.0.20200520" "v1.0.20200330" "v0.0.20200105"; do echo "**** Building the module ****" - if ! [ -z ${release} ] ; then - echo "Wireguard release ${release} set, checking out correct version" - cd wireguard-linux-compat - git checkout $release - cd .. + if ! [ -z ${release} ]; then + echo "Wireguard release ${release} set, checking out correct version" + cd wireguard-linux-compat + git checkout $release + cd .. fi make -C wireguard-linux-compat/src -j$(nproc) && returncode=$? || returncode=$? if [ $returncode -ne 0 ]; then continue; fi - make -C wireguard-linux-compat/src install && returncode=$? || returncode=$? - if [ $returncode -eq 0 ] ; then break; fi + make -C wireguard-linux-compat/src install && returncode=$? || returncode=$? + if [ $returncode -eq 0 ]; then break; fi done echo "**** Let's test our new module. ****" ip link del dev test 2>/dev/null @@ -166,20 +166,20 @@ rm -rf /etc/wireguard mkdir -p /etc/wireguard ln -s /config/wg0.conf /etc/wireguard/wg0.conf # prepare templates -[[ ! -f /config/templates/server.conf ]] && \ +[[ ! -f /config/templates/server.conf ]] && cp /defaults/server.conf /config/templates/server.conf -[[ ! -f /config/templates/peer.conf ]] && \ +[[ ! -f /config/templates/peer.conf ]] && cp /defaults/peer.conf /config/templates/peer.conf -generate_confs () { +generate_confs() { mkdir -p /config/server if [ ! -f /config/server/privatekey-server ]; then umask 077 - wg genkey | tee /config/server/privatekey-server | wg pubkey > /config/server/publickey-server + wg genkey | tee /config/server/privatekey-server | wg pubkey >/config/server/publickey-server fi - eval "`printf %s` + eval "$(printf %s) cat < /config/wg0.conf -`cat /config/templates/server.conf` +$(cat /config/templates/server.conf) DUDE" for i in ${PEERS_ARRAY[@]}; do @@ -191,7 +191,7 @@ DUDE" mkdir -p /config/${PEER_ID} if [ ! -f "/config/${PEER_ID}/privatekey-${PEER_ID}" ]; then umask 077 - wg genkey | tee /config/${PEER_ID}/privatekey-${PEER_ID} | wg pubkey > /config/${PEER_ID}/publickey-${PEER_ID} + wg genkey | tee /config/${PEER_ID}/privatekey-${PEER_ID} | wg pubkey >/config/${PEER_ID}/publickey-${PEER_ID} fi if [ -f "/config/${PEER_ID}/${PEER_ID}.conf" ]; then CLIENT_IP=$(cat /config/${PEER_ID}/${PEER_ID}.conf | grep "Address" | awk '{print $NF}') @@ -207,11 +207,11 @@ DUDE" fi done fi - eval "`printf %s` + eval "$(printf %s) cat < /config/${PEER_ID}/${PEER_ID}.conf -`cat /config/templates/peer.conf` +$(cat /config/templates/peer.conf) DUDE" - cat <> /config/wg0.conf + cat <>/config/wg0.conf [Peer] # ${PEER_ID} PublicKey = $(cat /config/${PEER_ID}/publickey-${PEER_ID}) @@ -219,13 +219,13 @@ AllowedIPs = ${CLIENT_IP}/32 DUDE echo "PEER ${i} QR code:" - qrencode -t ansiutf8 < /config/${PEER_ID}/${PEER_ID}.conf - qrencode -o /config/${PEER_ID}/${PEER_ID}.png < /config/${PEER_ID}/${PEER_ID}.conf + qrencode -t ansiutf8 /config/.donoteditthisfile +save_vars() { + cat </config/.donoteditthisfile ORIG_SERVERURL="$SERVERURL" ORIG_SERVERPORT="$SERVERPORT" ORIG_PEERDNS="$PEERDNS" @@ -245,28 +245,34 @@ if [ -n "$PEERS" ]; then PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - function fetchDappnodeDomain { - for i in {1..30}; do + # If _DAPPNODE_GLOBAL_HOSTNAME is set, use it as SERVERURL + if [ ! -z "$_DAPPNODE_GLOBAL_HOSTNAME" ]; then + echo "**** _DAPPNODE_GLOBAL_HOSTNAME is set, using it as SERVERURL ****" + SERVERURL="$_DAPPNODE_GLOBAL_HOSTNAME" + else + + function fetchDappnodeDomain { + for i in {1..30}; do for domain in "$@"; do - echo "**** Fetching DAppNode domain from $domain..." - SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") - if [ ! -z "$SERVERURL" ]; then - break 2 - fi - sleep 2 + echo "**** Fetching DAppNode domain from $domain..." + SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") + if [ ! -z "$SERVERURL" ]; then + break 2 + fi + sleep 2 done - done - } + done + } - # TODO: Remove IP when the IP migration is performed - domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7") + domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7" "10.20.0.7") - fetchDappnodeDomain "${domains[@]}" + fetchDappnodeDomain "${domains[@]}" + fi if [ -z "$SERVERURL" ]; then - echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" + echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" else - echo "**** SERVERURL var is set to $SERVERURL ****" + echo "**** SERVERURL var is set to $SERVERURL ****" fi else echo "**** External server address is set to $SERVERURL ****" @@ -291,7 +297,7 @@ if [ -n "$PEERS" ]; then save_vars else echo "**** Server mode is selected ****" - [[ -f /config/.donoteditthisfile ]] && \ + [[ -f /config/.donoteditthisfile ]] && . /config/.donoteditthisfile if [ "$SERVERURL" != "$ORIG_SERVERURL" ] || [ "$SERVERPORT" != "$ORIG_SERVERPORT" ] || [ "$PEERDNS" != "$ORIG_PEERDNS" ] || [ "$PEERS" != "$ORIG_PEERS" ] || [ "$INTERFACE" != "$ORIG_INTERFACE" ] || [ "$ALLOWEDIPS" != "$ORIG_ALLOWEDIPS" ]; then echo "**** Server related environment variables changed, regenerating 1 server and ${PEERS} peer/client confs ****" @@ -312,9 +318,9 @@ else fi # set up CoreDNS -[[ ! -f /config/coredns/Corefile ]] && \ +[[ ! -f /config/coredns/Corefile ]] && cp /defaults/Corefile /config/coredns/Corefile # permissions chown -R abc:abc \ - /config + /config From 6f169996ab4328395ef7238696f227554c80a714 Mon Sep 17 00:00:00 2001 From: Luka Gulin Date: Thu, 18 Jan 2024 17:01:44 +0100 Subject: [PATCH 56/57] Update upstream --- .editorconfig | 20 + .github/CONTRIBUTING.md | 9 +- .github/ISSUE_TEMPLATE/issue.bug.md | 40 -- .github/ISSUE_TEMPLATE/issue.bug.yml | 76 ++++ .github/ISSUE_TEMPLATE/issue.feature.md | 25 - .github/ISSUE_TEMPLATE/issue.feature.yml | 31 ++ .github/PULL_REQUEST_TEMPLATE.md | 6 +- .github/workflows/call_issue_pr_tracker.yml | 16 + .github/workflows/call_issues_cron.yml | 13 + .github/workflows/external_trigger.yml | 20 +- .../workflows/external_trigger_scheduler.yml | 20 +- .github/workflows/greetings.yml | 2 +- .github/workflows/package_trigger.yml | 6 +- .../workflows/package_trigger_scheduler.yml | 12 +- .github/workflows/permissions.yml | 10 + .github/workflows/stale.yml | 23 - Dockerfile | 93 ++-- Dockerfile.aarch64 | 93 ++-- Dockerfile.armhf | 65 --- README.md | 234 ++++++---- api/src/index.ts | 5 +- package_versions.txt | 430 +++++++++--------- readme-vars.yml | 74 ++- root/app/add-peer | 72 --- root/app/show-peer | 5 +- root/defaults/Corefile | 3 +- root/defaults/peer.conf | 3 +- root/etc/cont-init.d/30-config | 326 ------------- .../dependencies.d/init-wireguard-confs | 0 .../dependencies.d/init-wireguard-module | 0 .../s6-rc.d/init-wireguard-confs/run | 221 +++++++++ .../s6-rc.d/init-wireguard-confs/type | 1 + .../s6-rc.d/init-wireguard-confs/up | 1 + .../dependencies.d/init-config | 0 .../s6-rc.d/init-wireguard-module/run | 18 + .../s6-rc.d/init-wireguard-module/type | 1 + .../s6-rc.d/init-wireguard-module/up | 1 + .../svc-coredns/dependencies.d/init-services | 0 .../s6-rc.d/svc-coredns/notification-fd | 1 + root/etc/s6-overlay/s6-rc.d/svc-coredns/run | 23 + root/etc/s6-overlay/s6-rc.d/svc-coredns/type | 1 + .../svc-wireguard/dependencies.d/svc-coredns | 0 .../etc/s6-overlay/s6-rc.d/svc-wireguard/down | 1 + .../s6-overlay/s6-rc.d/svc-wireguard/finish | 4 + root/etc/s6-overlay/s6-rc.d/svc-wireguard/run | 4 + .../etc/s6-overlay/s6-rc.d/svc-wireguard/type | 1 + root/etc/s6-overlay/s6-rc.d/svc-wireguard/up | 1 + .../user/contents.d/init-wireguard-confs | 0 .../user/contents.d/init-wireguard-module | 0 .../s6-rc.d/user/contents.d/svc-coredns | 0 .../s6-rc.d/user/contents.d/svc-wireguard | 0 root/etc/services.d/coredns/run | 11 - root/etc/services.d/wireguard/run | 14 - 53 files changed, 1001 insertions(+), 1035 deletions(-) create mode 100755 .editorconfig delete mode 100755 .github/ISSUE_TEMPLATE/issue.bug.md create mode 100644 .github/ISSUE_TEMPLATE/issue.bug.yml delete mode 100755 .github/ISSUE_TEMPLATE/issue.feature.md create mode 100644 .github/ISSUE_TEMPLATE/issue.feature.yml create mode 100755 .github/workflows/call_issue_pr_tracker.yml create mode 100755 .github/workflows/call_issues_cron.yml create mode 100755 .github/workflows/permissions.yml delete mode 100644 .github/workflows/stale.yml delete mode 100644 Dockerfile.armhf delete mode 100755 root/app/add-peer delete mode 100644 root/etc/cont-init.d/30-config create mode 100644 root/etc/s6-overlay/s6-rc.d/init-config-end/dependencies.d/init-wireguard-confs create mode 100644 root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/dependencies.d/init-wireguard-module create mode 100755 root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/run create mode 100644 root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/type create mode 100644 root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/up create mode 100644 root/etc/s6-overlay/s6-rc.d/init-wireguard-module/dependencies.d/init-config create mode 100755 root/etc/s6-overlay/s6-rc.d/init-wireguard-module/run create mode 100644 root/etc/s6-overlay/s6-rc.d/init-wireguard-module/type create mode 100644 root/etc/s6-overlay/s6-rc.d/init-wireguard-module/up create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-coredns/dependencies.d/init-services create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-coredns/notification-fd create mode 100755 root/etc/s6-overlay/s6-rc.d/svc-coredns/run create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-coredns/type create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-wireguard/dependencies.d/svc-coredns create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-wireguard/down create mode 100755 root/etc/s6-overlay/s6-rc.d/svc-wireguard/finish create mode 100755 root/etc/s6-overlay/s6-rc.d/svc-wireguard/run create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-wireguard/type create mode 100644 root/etc/s6-overlay/s6-rc.d/svc-wireguard/up create mode 100644 root/etc/s6-overlay/s6-rc.d/user/contents.d/init-wireguard-confs create mode 100644 root/etc/s6-overlay/s6-rc.d/user/contents.d/init-wireguard-module create mode 100644 root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-coredns create mode 100644 root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-wireguard delete mode 100644 root/etc/services.d/coredns/run delete mode 100644 root/etc/services.d/wireguard/run diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 00000000..5f150f35 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# This file is globally distributed to all container image projects from +# https://github.com/linuxserver/docker-jenkins-builder/blob/master/.editorconfig + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +# trim_trailing_whitespace may cause unintended issues and should not be globally set true +trim_trailing_whitespace = false + +[{Dockerfile*,**.yml}] +indent_style = space +indent_size = 2 + +[{**.sh,root/etc/s6-overlay/s6-rc.d/**,root/etc/cont-init.d/**,root/etc/services.d/**}] +indent_style = space +indent_size = 4 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 406c0b30..d5ae6896 100755 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -4,7 +4,7 @@ * While contributing make sure to make all your changes before creating a Pull Request, as our pipeline builds each commit after the PR is open. * Read, and fill the Pull Request template - * If this is a fix for a typo in code or documentation in the README please file an issue + * If this is a fix for a typo (in code, documentation, or the README) please file an issue and let us sort it out. We do not need a PR * If the PR is addressing an existing issue include, closes #\, in the body of the PR commit message * If you want to discuss changes, you can also bring it up in [#dev-talk](https://discordapp.com/channels/354974912613449730/757585807061155840) in our [Discord server](https://discord.gg/YWrKVTn) @@ -96,7 +96,7 @@ If you are proposing additional packages to be added, ensure that you added the ### Testing your changes -``` +```bash git clone https://github.com/linuxserver/docker-wireguard.git cd docker-wireguard docker build \ @@ -106,13 +106,14 @@ docker build \ ``` The ARM variants can be built on x86_64 hardware using `multiarch/qemu-user-static` -``` + +```bash docker run --rm --privileged multiarch/qemu-user-static:register --reset ``` Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64`. -## Update the chagelog +## Update the changelog If you are modifying the Dockerfiles or any of the startup scripts in [root](https://github.com/linuxserver/docker-wireguard/tree/master/root), add an entry to the changelog diff --git a/.github/ISSUE_TEMPLATE/issue.bug.md b/.github/ISSUE_TEMPLATE/issue.bug.md deleted file mode 100755 index 5212eb17..00000000 --- a/.github/ISSUE_TEMPLATE/issue.bug.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve - ---- -[linuxserverurl]: https://linuxserver.io -[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] - - - - - ------------------------------- - -## Expected Behavior - - -## Current Behavior - - -## Steps to Reproduce - - -1. -2. -3. -4. - -## Environment -**OS:** -**CPU architecture:** x86_64/arm32/arm64 -**How docker service was installed:** - - - -## Command used to create docker container (run/create/compose/screenshot) - - -## Docker logs - diff --git a/.github/ISSUE_TEMPLATE/issue.bug.yml b/.github/ISSUE_TEMPLATE/issue.bug.yml new file mode 100644 index 00000000..ce3d19af --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue.bug.yml @@ -0,0 +1,76 @@ +# Based on the issue template +name: Bug report +description: Create a report to help us improve +title: "[BUG] " +labels: [Bug] +body: + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Current Behavior + description: Tell us what happens instead of the expected behavior. + validations: + required: true + - type: textarea + attributes: + label: Expected Behavior + description: Tell us what should happen. + validations: + required: false + - type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. In this environment... + 2. With this config... + 3. Run '...' + 4. See error... + validations: + required: true + - type: textarea + attributes: + label: Environment + description: | + examples: + - **OS**: Ubuntu 20.04 + - **How docker service was installed**: distro's packagemanager + value: | + - OS: + - How docker service was installed: + render: markdown + validations: + required: false + - type: dropdown + attributes: + label: CPU architecture + options: + - x86-64 + - arm64 + validations: + required: true + - type: textarea + attributes: + label: Docker creation + description: | + Command used to create docker container + Provide your docker create/run command or compose yaml snippet, or a screenshot of settings if using a gui to create the container + render: bash + validations: + required: true + - type: textarea + attributes: + description: | + Provide a full docker log, output of "docker logs linuxserver.io" + label: Container logs + placeholder: | + Output of `docker logs linuxserver.io` + render: bash + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/issue.feature.md b/.github/ISSUE_TEMPLATE/issue.feature.md deleted file mode 100755 index 20a91fdb..00000000 --- a/.github/ISSUE_TEMPLATE/issue.feature.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- -[linuxserverurl]: https://linuxserver.io -[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][linuxserverurl] - -<!--- If you are new to Docker or this application our issue tracker is **ONLY** used for reporting bugs or requesting features. Please use [our discord server](https://discord.gg/YWrKVTn) for general support. ---> - -<!--- If this acts as a feature request please ask yourself if this modification is something the whole userbase will benefit from ---> -<!--- If this is a specific change for corner case functionality or plugins please look at making a Docker Mod or local script https://blog.linuxserver.io/2019/09/14/customizing-our-containers/ --> - -<!--- Provide a general summary of the request in the Title above --> - ------------------------------- - -## Desired Behavior -<!--- Tell us what should happen --> - -## Current Behavior -<!--- Tell us what happens instead of the expected behavior --> - -## Alternatives Considered -<!--- Tell us what other options you have tried or considered --> diff --git a/.github/ISSUE_TEMPLATE/issue.feature.yml b/.github/ISSUE_TEMPLATE/issue.feature.yml new file mode 100644 index 00000000..099dcdb5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue.feature.yml @@ -0,0 +1,31 @@ +# Based on the issue template +name: Feature request +description: Suggest an idea for this project +title: "[FEAT] <title>" +labels: [enhancement] +body: + - type: checkboxes + attributes: + label: Is this a new feature request? + description: Please search to see if a feature request already exists. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Wanted change + description: Tell us what you want to happen. + validations: + required: true + - type: textarea + attributes: + label: Reason for change + description: Justify your request, why do you want it, what is the benefit. + validations: + required: true + - type: textarea + attributes: + label: Proposed code change + description: Do you have a potential code change in mind? + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 129db85f..e4a9091b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -15,7 +15,11 @@ **What does this PR do? Why is it needed?** -**How can be tested?** +<!--- If this is a fix for a typo (in code, documentation, or the README) please file an issue and let us sort it out. We do not need a PR --> +<!--- Ask yourself if this modification is something the whole userbase will benefit from, if this is a specific change for corner case functionality or plugins please look at making a Docker Mod or local script https://blog.linuxserver.io/2019/09/14/customizing-our-containers/ --> +<!--- That if the PR is addressing an existing issue include, closes #<issue number> , in the body of the PR commit message --> +<!--- You have included links to any files / patches etc your PR may be using in the body of the PR commit message --> +<!--- We maintain a changelog of major revisions to the container at the end of readme-vars.yml in the root of this repository, please add your changes there if appropriate --> > Provide well detailed instructions to test this PR diff --git a/.github/workflows/call_issue_pr_tracker.yml b/.github/workflows/call_issue_pr_tracker.yml new file mode 100755 index 00000000..2c307843 --- /dev/null +++ b/.github/workflows/call_issue_pr_tracker.yml @@ -0,0 +1,16 @@ +name: Issue & PR Tracker + +on: + issues: + types: [opened,reopened,labeled,unlabeled,closed] + pull_request_target: + types: [opened,reopened,review_requested,review_request_removed,labeled,unlabeled,closed] + pull_request_review: + types: [submitted,edited,dismissed] + +jobs: + manage-project: + permissions: + issues: write + uses: linuxserver/github-workflows/.github/workflows/issue-pr-tracker.yml@v1 + secrets: inherit diff --git a/.github/workflows/call_issues_cron.yml b/.github/workflows/call_issues_cron.yml new file mode 100755 index 00000000..091b04a7 --- /dev/null +++ b/.github/workflows/call_issues_cron.yml @@ -0,0 +1,13 @@ +name: Mark stale issues and pull requests +on: + schedule: + - cron: '20 0 * * *' + workflow_dispatch: + +jobs: + stale: + permissions: + issues: write + pull-requests: write + uses: linuxserver/github-workflows/.github/workflows/issues-cron.yml@v1 + secrets: inherit diff --git a/.github/workflows/external_trigger.yml b/.github/workflows/external_trigger.yml index b7bce8e6..b4537edd 100755 --- a/.github/workflows/external_trigger.yml +++ b/.github/workflows/external_trigger.yml @@ -7,18 +7,20 @@ jobs: external-trigger-master: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v3.1.0 - name: External Trigger if: github.ref == 'refs/heads/master' run: | if [ -n "${{ secrets.PAUSE_EXTERNAL_TRIGGER_WIREGUARD_MASTER }}" ]; then echo "**** Github secret PAUSE_EXTERNAL_TRIGGER_WIREGUARD_MASTER is set; skipping trigger. ****" + echo "Github secret \`PAUSE_EXTERNAL_TRIGGER_WIREGUARD_MASTER\` is set; skipping trigger." >> $GITHUB_STEP_SUMMARY exit 0 fi echo "**** External trigger running off of master branch. To disable this trigger, set a Github secret named \"PAUSE_EXTERNAL_TRIGGER_WIREGUARD_MASTER\". ****" + echo "External trigger running off of master branch. To disable this trigger, set a Github secret named \`PAUSE_EXTERNAL_TRIGGER_WIREGUARD_MASTER\`" >> $GITHUB_STEP_SUMMARY echo "**** Retrieving external version ****" - EXT_RELEASE=$(curl -sX GET https://api.github.com/repos/WireGuard/wireguard-tools/tags | jq -r .[0].name) + EXT_RELEASE=$(curl -u ${{ secrets.CR_USER }}:${{ secrets.CR_PAT }} -sX GET https://api.github.com/repos/WireGuard/wireguard-tools/tags | jq -r .[0].name) if [ -z "${EXT_RELEASE}" ] || [ "${EXT_RELEASE}" == "null" ]; then echo "**** Can't retrieve external version, exiting ****" FAILURE_REASON="Can't retrieve external version for wireguard branch master" @@ -30,6 +32,7 @@ jobs: fi EXT_RELEASE=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g') echo "**** External version: ${EXT_RELEASE} ****" + echo "External version: ${EXT_RELEASE}" >> $GITHUB_STEP_SUMMARY echo "**** Retrieving last pushed version ****" image="linuxserver/wireguard" tag="latest" @@ -48,8 +51,12 @@ jobs: | jq -r '.config.digest') image_info=$(curl -sL \ --header "Authorization: Bearer ${token}" \ - "https://ghcr.io/v2/${image}/blobs/${digest}" \ - | jq -r '.container_config') + "https://ghcr.io/v2/${image}/blobs/${digest}") + if [[ $(echo $image_info | jq -r '.container_config') == "null" ]]; then + image_info=$(echo $image_info | jq -r '.config') + else + image_info=$(echo $image_info | jq -r '.container_config') + fi IMAGE_RELEASE=$(echo ${image_info} | jq -r '.Labels.build_version' | awk '{print $3}') IMAGE_VERSION=$(echo ${IMAGE_RELEASE} | awk -F'-ls' '{print $1}') if [ -z "${IMAGE_VERSION}" ]; then @@ -61,14 +68,18 @@ jobs: exit 1 fi echo "**** Last pushed version: ${IMAGE_VERSION} ****" + echo "Last pushed version: ${IMAGE_VERSION}" >> $GITHUB_STEP_SUMMARY if [ "${EXT_RELEASE}" == "${IMAGE_VERSION}" ]; then echo "**** Version ${EXT_RELEASE} already pushed, exiting ****" + echo "Version ${EXT_RELEASE} already pushed, exiting" >> $GITHUB_STEP_SUMMARY exit 0 elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-wireguard/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then echo "**** New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting ****" + echo "New version ${EXT_RELEASE} found; but there already seems to be an active build on Jenkins; exiting" >> $GITHUB_STEP_SUMMARY exit 0 else echo "**** New version ${EXT_RELEASE} found; old version was ${IMAGE_VERSION}. Triggering new build ****" + echo "New version ${EXT_RELEASE} found; old version was ${IMAGE_VERSION}. Triggering new build" >> $GITHUB_STEP_SUMMARY response=$(curl -iX POST \ https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-wireguard/job/master/buildWithParameters?PACKAGE_CHECK=false \ --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") @@ -78,6 +89,7 @@ jobs: buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') buildurl="${buildurl%$'\r'}" echo "**** Jenkins job build url: ${buildurl} ****" + echo "Jenkins job build url: ${buildurl}" >> $GITHUB_STEP_SUMMARY echo "**** Attempting to change the Jenkins job description ****" curl -iX POST \ "${buildurl}submitDescription" \ diff --git a/.github/workflows/external_trigger_scheduler.yml b/.github/workflows/external_trigger_scheduler.yml index a9830deb..61c03c71 100755 --- a/.github/workflows/external_trigger_scheduler.yml +++ b/.github/workflows/external_trigger_scheduler.yml @@ -2,14 +2,14 @@ name: External Trigger Scheduler on: schedule: - - cron: '25 * * * *' + - cron: '51 * * * *' workflow_dispatch: jobs: external-trigger-scheduler: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v3.1.0 with: fetch-depth: '0' @@ -17,18 +17,18 @@ jobs: run: | echo "**** Branches found: ****" git for-each-ref --format='%(refname:short)' refs/remotes - echo "**** Pulling the yq docker image ****" - docker pull ghcr.io/linuxserver/yq for br in $(git for-each-ref --format='%(refname:short)' refs/remotes) do br=$(echo "$br" | sed 's|origin/||g') echo "**** Evaluating branch ${br} ****" - ls_branch=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-wireguard/${br}/jenkins-vars.yml \ - | docker run --rm -i --entrypoint yq ghcr.io/linuxserver/yq -r .ls_branch) - if [ "$br" == "$ls_branch" ]; then - echo "**** Branch ${br} appears to be live; checking workflow. ****" + ls_jenkins_vars=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-wireguard/${br}/jenkins-vars.yml) + ls_branch=$(echo "${ls_jenkins_vars}" | yq -r '.ls_branch') + ls_trigger=$(echo "${ls_jenkins_vars}" | yq -r '.external_type') + if [[ "${br}" == "${ls_branch}" ]] && [[ "${ls_trigger}" != "os" ]]; then + echo "**** Branch ${br} appears to be live and trigger is not os; checking workflow. ****" if curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-wireguard/${br}/.github/workflows/external_trigger.yml > /dev/null 2>&1; then echo "**** Workflow exists. Triggering external trigger workflow for branch ${br} ****." + echo "Triggering external trigger workflow for branch ${br}" >> $GITHUB_STEP_SUMMARY curl -iX POST \ -H "Authorization: token ${{ secrets.CR_PAT }}" \ -H "Accept: application/vnd.github.v3+json" \ @@ -36,8 +36,10 @@ jobs: https://api.github.com/repos/linuxserver/docker-wireguard/actions/workflows/external_trigger.yml/dispatches else echo "**** Workflow doesn't exist; skipping trigger. ****" + echo "Skipping branch ${br} due to no external trigger workflow present." >> $GITHUB_STEP_SUMMARY fi else - echo "**** ${br} appears to be a dev branch; skipping trigger. ****" + echo "**** ${br} is either a dev branch, or has no external version; skipping trigger. ****" + echo "Skipping branch ${br} due to being detected as dev branch or having no external version." >> $GITHUB_STEP_SUMMARY fi done diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index d10ccf2f..f3cc4efe 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -8,6 +8,6 @@ jobs: steps: - uses: actions/first-interaction@v1 with: - issue-message: 'Thanks for opening your first issue here! Be sure to follow the [bug](https://github.com/linuxserver/docker-wireguard/blob/master/.github/ISSUE_TEMPLATE/issue.bug.md) or [feature](https://github.com/linuxserver/docker-wireguard/blob/master/.github/ISSUE_TEMPLATE/issue.feature.md) issue templates!' + issue-message: 'Thanks for opening your first issue here! Be sure to follow the relevant issue templates, or risk having this issue marked as invalid.' pr-message: 'Thanks for opening this pull request! Be sure to follow the [pull request template](https://github.com/linuxserver/docker-wireguard/blob/master/.github/PULL_REQUEST_TEMPLATE.md)!' repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/package_trigger.yml b/.github/workflows/package_trigger.yml index 8c10ea54..32bf4865 100755 --- a/.github/workflows/package_trigger.yml +++ b/.github/workflows/package_trigger.yml @@ -7,20 +7,23 @@ jobs: package-trigger-master: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v3.1.0 - name: Package Trigger if: github.ref == 'refs/heads/master' run: | if [ -n "${{ secrets.PAUSE_PACKAGE_TRIGGER_WIREGUARD_MASTER }}" ]; then echo "**** Github secret PAUSE_PACKAGE_TRIGGER_WIREGUARD_MASTER is set; skipping trigger. ****" + echo "Github secret \`PAUSE_PACKAGE_TRIGGER_WIREGUARD_MASTER\` is set; skipping trigger." >> $GITHUB_STEP_SUMMARY exit 0 fi if [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-wireguard/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then echo "**** There already seems to be an active build on Jenkins; skipping package trigger ****" + echo "There already seems to be an active build on Jenkins; skipping package trigger" >> $GITHUB_STEP_SUMMARY exit 0 fi echo "**** Package trigger running off of master branch. To disable, set a Github secret named \"PAUSE_PACKAGE_TRIGGER_WIREGUARD_MASTER\". ****" + echo "Package trigger running off of master branch. To disable, set a Github secret named \`PAUSE_PACKAGE_TRIGGER_WIREGUARD_MASTER\`" >> $GITHUB_STEP_SUMMARY response=$(curl -iX POST \ https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-wireguard/job/master/buildWithParameters?PACKAGE_CHECK=true \ --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") @@ -30,6 +33,7 @@ jobs: buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url') buildurl="${buildurl%$'\r'}" echo "**** Jenkins job build url: ${buildurl} ****" + echo "Jenkins job build url: ${buildurl}" >> $GITHUB_STEP_SUMMARY echo "**** Attempting to change the Jenkins job description ****" curl -iX POST \ "${buildurl}submitDescription" \ diff --git a/.github/workflows/package_trigger_scheduler.yml b/.github/workflows/package_trigger_scheduler.yml index 43a87b0c..bb2efa7c 100755 --- a/.github/workflows/package_trigger_scheduler.yml +++ b/.github/workflows/package_trigger_scheduler.yml @@ -2,14 +2,14 @@ name: Package Trigger Scheduler on: schedule: - - cron: '41 1 * * 0' + - cron: '9 11 * * 4' workflow_dispatch: jobs: package-trigger-scheduler: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.3 + - uses: actions/checkout@v3.1.0 with: fetch-depth: '0' @@ -17,18 +17,16 @@ jobs: run: | echo "**** Branches found: ****" git for-each-ref --format='%(refname:short)' refs/remotes - echo "**** Pulling the yq docker image ****" - docker pull ghcr.io/linuxserver/yq for br in $(git for-each-ref --format='%(refname:short)' refs/remotes) do br=$(echo "$br" | sed 's|origin/||g') echo "**** Evaluating branch ${br} ****" - ls_branch=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-wireguard/${br}/jenkins-vars.yml \ - | docker run --rm -i --entrypoint yq ghcr.io/linuxserver/yq -r .ls_branch) + ls_branch=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-wireguard/${br}/jenkins-vars.yml | yq -r '.ls_branch') if [ "${br}" == "${ls_branch}" ]; then echo "**** Branch ${br} appears to be live; checking workflow. ****" if curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-wireguard/${br}/.github/workflows/package_trigger.yml > /dev/null 2>&1; then echo "**** Workflow exists. Triggering package trigger workflow for branch ${br}. ****" + echo "Triggering package trigger workflow for branch ${br}" >> $GITHUB_STEP_SUMMARY triggered_branches="${triggered_branches}${br} " curl -iX POST \ -H "Authorization: token ${{ secrets.CR_PAT }}" \ @@ -38,9 +36,11 @@ jobs: sleep 30 else echo "**** Workflow doesn't exist; skipping trigger. ****" + echo "Skipping branch ${br} due to no package trigger workflow present." >> $GITHUB_STEP_SUMMARY fi else echo "**** ${br} appears to be a dev branch; skipping trigger. ****" + echo "Skipping branch ${br} due to being detected as dev branch." >> $GITHUB_STEP_SUMMARY fi done echo "**** Package check build(s) triggered for branch(es): ${triggered_branches} ****" diff --git a/.github/workflows/permissions.yml b/.github/workflows/permissions.yml new file mode 100755 index 00000000..1447bc55 --- /dev/null +++ b/.github/workflows/permissions.yml @@ -0,0 +1,10 @@ +name: Permission check +on: + pull_request_target: + paths: + - '**/run' + - '**/finish' + - '**/check' +jobs: + permission_check: + uses: linuxserver/github-workflows/.github/workflows/init-svc-executable-permissions.yml@v1 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 1806420a..00000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Mark stale issues and pull requests - -on: - schedule: - - cron: "30 1 * * *" - -jobs: - stale: - - runs-on: ubuntu-latest - - steps: - - uses: actions/stale@v1 - with: - stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." - stale-pr-message: "This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' - days-before-stale: 30 - days-before-close: 365 - exempt-issue-labels: 'awaiting-approval,work-in-progress' - exempt-pr-labels: 'awaiting-approval,work-in-progress' - repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 7273fc73..f7ab111d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:focal +# syntax=docker/dockerfile:1 + +FROM ghcr.io/linuxserver/baseimage-alpine:3.18 # set version label ARG BUILD_DATE @@ -6,58 +8,47 @@ ARG VERSION ARG WIREGUARD_RELEASE ARG TARGETPLATFORM LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="aptalca" - -ENV DEBIAN_FRONTEND="noninteractive" +LABEL maintainer="thespad" RUN \ - echo "**** install dependencies ****" && \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - bc \ - build-essential \ - curl \ - dkms \ - git \ - gnupg \ - ifupdown \ - iproute2 \ - iptables \ - iputils-ping \ - jq \ - libc6 \ - libelf-dev \ - net-tools \ - openresolv \ - perl \ - pkg-config \ - qrencode && \ - echo "**** install wireguard-tools ****" && \ - if [ -z ${WIREGUARD_RELEASE+x} ]; then \ - WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ - | jq -r .[0].name); \ - fi && \ - cd /app && \ - git clone https://git.zx2c4.com/wireguard-linux-compat && \ - git clone https://git.zx2c4.com/wireguard-tools && \ - cd wireguard-tools && \ - git checkout "${WIREGUARD_RELEASE}" && \ - make -C src -j$(nproc) && \ - make -C src install && \ - echo "**** install CoreDNS ****" && \ - COREDNS_VERSION=$(curl -sX GET "https://api.github.com/repos/coredns/coredns/releases/latest" \ - | awk '/tag_name/{print $4;exit}' FS='[""]' | awk '{print substr($1,2); }') && \ - curl -o \ - /tmp/coredns.tar.gz -L \ - "https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_$(echo ${TARGETPLATFORM:-linux/amd64} | sed 's:/:_:g' | sed 's/arm_v7/arm/').tgz" && \ - tar xf \ - /tmp/coredns.tar.gz -C \ - /app && \ - echo "**** clean up ****" && \ - rm -rf \ - /tmp/* \ - /var/lib/apt/lists/* \ - /var/tmp/* + echo "**** install dependencies ****" && \ + apk add --no-cache --virtual=build-dependencies \ + build-base \ + elfutils-dev \ + gcc \ + git \ + linux-headers && \ + apk add --no-cache \ + bc \ + coredns \ + gnupg \ + grep \ + iproute2 \ + iptables \ + ip6tables \ + iputils \ + libcap-utils \ + libqrencode \ + net-tools \ + openresolv \ + perl && \ + echo "wireguard" >> /etc/modules && \ + echo "**** install wireguard-tools ****" && \ + if [ -z ${WIREGUARD_RELEASE+x} ]; then \ + WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ + | jq -r .[0].name); \ + fi && \ + cd /app && \ + git clone https://git.zx2c4.com/wireguard-tools && \ + cd wireguard-tools && \ + git checkout "${WIREGUARD_RELEASE}" && \ + sed -i 's|\[\[ $proto == -4 \]\] && cmd sysctl -q net\.ipv4\.conf\.all\.src_valid_mark=1|[[ $proto == -4 ]] \&\& [[ $(sysctl -n net.ipv4.conf.all.src_valid_mark) != 1 ]] \&\& cmd sysctl -q net.ipv4.conf.all.src_valid_mark=1|' src/wg-quick/linux.bash && \ + make -C src -j$(nproc) && \ + make -C src install && \ + echo "**** clean up ****" && \ + apk del --no-network build-dependencies && \ + rm -rf \ + /tmp/* # add local files COPY /root / diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index 18628487..9f478d89 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,62 +1,53 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:arm64v8-focal +# syntax=docker/dockerfile:1 + +FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.18 # set version label ARG BUILD_DATE ARG VERSION ARG WIREGUARD_RELEASE LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="aptalca" - -ENV DEBIAN_FRONTEND="noninteractive" +LABEL maintainer="thespad" RUN \ - echo "**** install dependencies ****" && \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - bc \ - build-essential \ - curl \ - dkms \ - git \ - gnupg \ - ifupdown \ - iproute2 \ - iptables \ - iputils-ping \ - jq \ - libc6 \ - libelf-dev \ - net-tools \ - openresolv \ - perl \ - pkg-config \ - qrencode && \ - echo "**** install wireguard-tools ****" && \ - if [ -z ${WIREGUARD_RELEASE+x} ]; then \ - WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ - | jq -r .[0].name); \ - fi && \ - cd /app && \ - git clone https://git.zx2c4.com/wireguard-linux-compat && \ - git clone https://git.zx2c4.com/wireguard-tools && \ - cd wireguard-tools && \ - git checkout "${WIREGUARD_RELEASE}" && \ - make -C src -j$(nproc) && \ - make -C src install && \ - echo "**** install CoreDNS ****" && \ - COREDNS_VERSION=$(curl -sX GET "https://api.github.com/repos/coredns/coredns/releases/latest" \ - | awk '/tag_name/{print $4;exit}' FS='[""]' | awk '{print substr($1,2); }') && \ - curl -o \ - /tmp/coredns.tar.gz -L \ - "https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_arm64.tgz" && \ - tar xf \ - /tmp/coredns.tar.gz -C \ - /app && \ - echo "**** clean up ****" && \ - rm -rf \ - /tmp/* \ - /var/lib/apt/lists/* \ - /var/tmp/* + echo "**** install dependencies ****" && \ + apk add --no-cache --virtual=build-dependencies \ + build-base \ + elfutils-dev \ + gcc \ + git \ + linux-headers && \ + apk add --no-cache \ + bc \ + coredns \ + gnupg \ + grep \ + iproute2 \ + iptables \ + ip6tables \ + iputils \ + libcap-utils \ + libqrencode \ + net-tools \ + openresolv \ + perl && \ + echo "wireguard" >> /etc/modules && \ + echo "**** install wireguard-tools ****" && \ + if [ -z ${WIREGUARD_RELEASE+x} ]; then \ + WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ + | jq -r .[0].name); \ + fi && \ + cd /app && \ + git clone https://git.zx2c4.com/wireguard-tools && \ + cd wireguard-tools && \ + git checkout "${WIREGUARD_RELEASE}" && \ + sed -i 's|\[\[ $proto == -4 \]\] && cmd sysctl -q net\.ipv4\.conf\.all\.src_valid_mark=1|[[ $proto == -4 ]] \&\& [[ $(sysctl -n net.ipv4.conf.all.src_valid_mark) != 1 ]] \&\& cmd sysctl -q net.ipv4.conf.all.src_valid_mark=1|' src/wg-quick/linux.bash && \ + make -C src -j$(nproc) && \ + make -C src install && \ + echo "**** clean up ****" && \ + apk del --no-network build-dependencies && \ + rm -rf \ + /tmp/* # add local files COPY /root / diff --git a/Dockerfile.armhf b/Dockerfile.armhf deleted file mode 100644 index 6cf259e3..00000000 --- a/Dockerfile.armhf +++ /dev/null @@ -1,65 +0,0 @@ -FROM ghcr.io/linuxserver/baseimage-ubuntu:arm32v7-focal - -# set version label -ARG BUILD_DATE -ARG VERSION -ARG WIREGUARD_RELEASE -LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}" -LABEL maintainer="aptalca" - -ENV DEBIAN_FRONTEND="noninteractive" - -RUN \ - echo "**** install dependencies ****" && \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - bc \ - build-essential \ - curl \ - dkms \ - git \ - gnupg \ - ifupdown \ - iproute2 \ - iptables \ - iputils-ping \ - jq \ - libc6 \ - libelf-dev \ - net-tools \ - openresolv \ - perl \ - pkg-config \ - qrencode && \ - echo "**** install wireguard-tools ****" && \ - if [ -z ${WIREGUARD_RELEASE+x} ]; then \ - WIREGUARD_RELEASE=$(curl -sX GET "https://api.github.com/repos/WireGuard/wireguard-tools/tags" \ - | jq -r .[0].name); \ - fi && \ - cd /app && \ - git clone https://git.zx2c4.com/wireguard-linux-compat && \ - git clone https://git.zx2c4.com/wireguard-tools && \ - cd wireguard-tools && \ - git checkout "${WIREGUARD_RELEASE}" && \ - make -C src -j$(nproc) && \ - make -C src install && \ - echo "**** install CoreDNS ****" && \ - COREDNS_VERSION=$(curl -sX GET "https://api.github.com/repos/coredns/coredns/releases/latest" \ - | awk '/tag_name/{print $4;exit}' FS='[""]' | awk '{print substr($1,2); }') && \ - curl -o \ - /tmp/coredns.tar.gz -L \ - "https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_arm.tgz" && \ - tar xf \ - /tmp/coredns.tar.gz -C \ - /app && \ - echo "**** clean up ****" && \ - rm -rf \ - /tmp/* \ - /var/lib/apt/lists/* \ - /var/tmp/* - -# add local files -COPY /root / - -# ports and volumes -EXPOSE 51820/udp diff --git a/README.md b/README.md index 60cbf78b..7752783f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ <!-- DO NOT EDIT THIS FILE MANUALLY --> -<!-- Please read the CONTRIBUTING.md --> +<!-- Please read the https://github.com/linuxserver/docker-wireguard/blob/master/.github/CONTRIBUTING.md --> [![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)](https://linuxserver.io) @@ -12,13 +12,14 @@ The [LinuxServer.io](https://linuxserver.io) team brings you another container release featuring: - * regular and timely application updates - * easy user mappings (PGID, PUID) - * custom base image with s6 overlay - * weekly base OS updates with common layers across the entire LinuxServer.io ecosystem to minimise space usage, down time and bandwidth - * regular security updates +* regular and timely application updates +* easy user mappings (PGID, PUID) +* custom base image with s6 overlay +* weekly base OS updates with common layers across the entire LinuxServer.io ecosystem to minimise space usage, down time and bandwidth +* regular security updates Find us at: + * [Blog](https://blog.linuxserver.io) - all the things you can do with our containers including How-To guides, opinions and much more! * [Discord](https://discord.gg/YWrKVTn) - realtime support / chat with the community and the team. * [Discourse](https://discourse.linuxserver.io) - post on our community forum. @@ -28,11 +29,12 @@ Find us at: # [linuxserver/wireguard](https://github.com/linuxserver/docker-wireguard) +[![Scarf.io pulls](https://scarf.sh/installs-badge/linuxserver-ci/linuxserver%2Fwireguard?color=94398d&label-color=555555&logo-color=ffffff&style=for-the-badge&package-type=docker)](https://scarf.sh/gateway/linuxserver-ci/docker/linuxserver%2Fwireguard) [![GitHub Stars](https://img.shields.io/github/stars/linuxserver/docker-wireguard.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-wireguard) [![GitHub Release](https://img.shields.io/github/release/linuxserver/docker-wireguard.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-wireguard/releases) [![GitHub Package Repository](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitHub%20Package&logo=github)](https://github.com/linuxserver/docker-wireguard/packages) [![GitLab Container Registry](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitLab%20Registry&logo=gitlab)](https://gitlab.com/linuxserver.io/docker-wireguard/container_registry) -[![MicroBadger Layers](https://img.shields.io/microbadger/layers/linuxserver/wireguard.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge)](https://microbadger.com/images/linuxserver/wireguard "Get your own version badge on microbadger.com") +[![Quay.io](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=Quay.io)](https://quay.io/repository/linuxserver.io/wireguard) [![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/wireguard.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=pulls&logo=docker)](https://hub.docker.com/r/linuxserver/wireguard) [![Docker Stars](https://img.shields.io/docker/stars/linuxserver/wireguard.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=stars&logo=docker)](https://hub.docker.com/r/linuxserver/wireguard) [![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-wireguard%2Fjob%2Fmaster%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-wireguard/job/master/) @@ -43,50 +45,122 @@ Find us at: ## Supported Architectures -Our images support multiple architectures such as `x86-64`, `arm64` and `armhf`. We utilise the docker manifest for multi-platform awareness. More information is available from docker [here](https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md#manifest-list) and our announcement [here](https://blog.linuxserver.io/2019/02/21/the-lsio-pipeline-project/). +We utilise the docker manifest for multi-platform awareness. More information is available from docker [here](https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md#manifest-list) and our announcement [here](https://blog.linuxserver.io/2019/02/21/the-lsio-pipeline-project/). -Simply pulling `ghcr.io/linuxserver/wireguard` should retrieve the correct image for your arch, but you can also pull specific arch images via tags. +Simply pulling `lscr.io/linuxserver/wireguard:latest` should retrieve the correct image for your arch, but you can also pull specific arch images via tags. The architectures supported by this image are: -| Architecture | Tag | -| :----: | --- | -| x86-64 | amd64-latest | -| arm64 | arm64v8-latest | -| armhf | arm32v7-latest | +| Architecture | Available | Tag | +| :----: | :----: | ---- | +| x86-64 | ✅ | amd64-\<version tag\> | +| arm64 | ✅ | arm64v8-\<version tag\> | +| armhf | ❌ | | + +## Version Tags + +This image provides various versions that are available via tags. Please read the descriptions carefully and exercise caution when using unstable or development tags. + +| Tag | Available | Description | +| :----: | :----: |--- | +| latest | ✅ | Stable releases based on Alpine *without* support for compiling Wireguard modules. | +| legacy | ✅ | Stable releases with support for compiling Wireguard modules for older kernels. | +## Application Setup + +During container start, it will first check if the wireguard module is already installed and loaded. Kernels newer than 5.6 generally have the wireguard module built-in (along with some older custom kernels). However, the module may not be enabled. Make sure it is enabled prior to starting the container. + +This can be run as a server or a client, based on the parameters used. + +## Note on iptables + +Some hosts may not load the iptables kernel modules by default. In order for the container to be able to load them, you need to assign the `SYS_MODULE` capability and add the optional `/lib/modules` volume mount. Alternatively you can `modprobe` them from the host before starting the container. + +## Server Mode + +If the environment variable `PEERS` is set to a number or a list of strings separated by comma, the container will run in server mode and the necessary server and peer/client confs will be generated. The peer/client config qr codes will be output in the docker log if `LOG_CONFS` is set to `true`. They will also be saved in text and png format under `/config/peerX` in case `PEERS` is a variable and an integer or `/config/peer_X` in case a list of names was provided instead of an integer. + +Variables `SERVERURL`, `SERVERPORT`, `INTERNAL_SUBNET`, `PEERDNS`, `INTERFACE`, `ALLOWEDIPS` and `PERSISTENTKEEPALIVE_PEERS` are optional variables used for server mode. Any changes to these environment variables will trigger regeneration of server and peer confs. Peer/client confs will be recreated with existing private/public keys. Delete the peer folders for the keys to be recreated along with the confs. + +To add more peers/clients later on, you increment the `PEERS` environment variable or add more elements to the list and recreate the container. + +To display the QR codes of active peers again, you can use the following command and list the peer numbers as arguments: `docker exec -it wireguard /app/show-peer 1 4 5` or `docker exec -it wireguard /app/show-peer myPC myPhone myTablet` (Keep in mind that the QR codes are also stored as PNGs in the config folder). + +The templates used for server and peer confs are saved under `/config/templates`. Advanced users can modify these templates and force conf generation by deleting `/config/wg0.conf` and restarting the container. + +## Client Mode + +Do not set the `PEERS` environment variable. Drop your client conf into the config folder as `/config/wg0.conf` and start the container. +If you get IPv6 related errors in the log and connection cannot be established, edit the `AllowedIPs` line in your peer/client wg0.conf to include only `0.0.0.0/0` and not `::/0`; and restart the container. + +## Road warriors, roaming and returning home + +If you plan to use Wireguard both remotely and locally, say on your mobile phone, you will need to consider routing. Most firewalls will not route ports forwarded on your WAN interface correctly to the LAN out of the box. This means that when you return home, even though you can see the Wireguard server, the return packets will probably get lost. + +This is not a Wireguard specific issue and the two generally accepted solutions are NAT reflection (setting your edge router/firewall up in such a way as it translates internal packets correctly) or split horizon DNS (setting your internal DNS to return the private rather than public IP when connecting locally). + +Both of these approaches have positives and negatives however their setup is out of scope for this document as everyone's network layout and equipment will be different. + +## Maintaining local access to attached services + +** Note: This is not a supported configuration by Linuxserver.io - use at your own risk. + +When routing via Wireguard from another container using the `service` option in docker, you might lose access to the containers webUI locally. To avoid this, exclude the docker subnet from being routed via Wireguard by modifying your `wg0.conf` like so (modifying the subnets as you require): + + ```ini + [Interface] + PrivateKey = <private key> + Address = 9.8.7.6/32 + DNS = 8.8.8.8 + PostUp = DROUTE=$(ip route | grep default | awk '{print $3}'); HOMENET=192.168.0.0/16; HOMENET2=10.0.0.0/8; HOMENET3=172.16.0.0/12; ip route add $HOMENET3 via $DROUTE;ip route add $HOMENET2 via $DROUTE; ip route add $HOMENET via $DROUTE;iptables -I OUTPUT -d $HOMENET -j ACCEPT;iptables -A OUTPUT -d $HOMENET2 -j ACCEPT; iptables -A OUTPUT -d $HOMENET3 -j ACCEPT; iptables -A OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT + PreDown = HOMENET=192.168.0.0/16; HOMENET2=10.0.0.0/8; HOMENET3=172.16.0.0/12; ip route del $HOMENET3 via $DROUTE;ip route del $HOMENET2 via $DROUTE; ip route del $HOMENET via $DROUTE; iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT; iptables -D OUTPUT -d $HOMENET -j ACCEPT; iptables -D OUTPUT -d $HOMENET2 -j ACCEPT; iptables -D OUTPUT -d $HOMENET3 -j ACCEPT + ``` + +## Site-to-site VPN + +** Note: This is not a supported configuration by Linuxserver.io - use at your own risk. + +Site-to-site VPN in server mode requires customizing the `AllowedIPs` statement for a specific peer in `wg0.conf`. Since `wg0.conf` is autogenerated when server vars are changed, it is not recommended to edit it manually. + +In order to customize the `AllowedIPs` statement for a specific peer in `wg0.conf`, you can set an env var `SERVER_ALLOWEDIPS_PEER_<peer name or number>` to the additional subnets you'd like to add, comma separated and excluding the peer IP (ie. `"192.168.1.0/24,192.168.2.0/24"`). Replace `<peer name or number>` with either the name or number of a peer (whichever is used in the `PEERS` var). + +For instance `SERVER_ALLOWEDIPS_PEER_laptop="192.168.1.0/24,192.168.2.0/24"` will result in the wg0.conf entry `AllowedIPs = 10.13.13.2,192.168.1.0/24,192.168.2.0/24` for the peer named `laptop`. + +Keep in mind that this var will only be considered when the confs are regenerated. Adding this var for an existing peer won't force a regeneration. You can delete wg0.conf and restart the container to force regeneration if necessary. + +Don't forget to set the necessary POSTUP and POSTDOWN rules in your client's peer conf for lan access. ## Usage Here are some example snippets to help you get started creating a container. -### docker-compose ([recommended](https://docs.linuxserver.io/general/docker-compose)) - -Compatible with docker-compose v2 schemas. +### docker-compose (recommended, [click here for more info](https://docs.linuxserver.io/general/docker-compose)) ```yaml --- version: "2.1" services: wireguard: - image: ghcr.io/linuxserver/wireguard + image: lscr.io/linuxserver/wireguard:latest container_name: wireguard cap_add: - NET_ADMIN - - SYS_MODULE + - SYS_MODULE #optional environment: - PUID=1000 - PGID=1000 - - TZ=Europe/London + - TZ=Etc/UTC - SERVERURL=wireguard.domain.com #optional - SERVERPORT=51820 #optional - PEERS=1 #optional - PEERDNS=auto #optional - INTERNAL_SUBNET=10.13.13.0 #optional - ALLOWEDIPS=0.0.0.0/0 #optional + - PERSISTENTKEEPALIVE_PEERS= #optional + - LOG_CONFS=true #optional volumes: - /path/to/appdata/config:/config - - /lib/modules:/lib/modules + - /lib/modules:/lib/modules #optional ports: - 51820:51820/udp sysctls: @@ -94,30 +168,32 @@ services: restart: unless-stopped ``` -### docker cli +### docker cli ([click here for more info](https://docs.docker.com/engine/reference/commandline/cli/)) -``` +```bash docker run -d \ --name=wireguard \ --cap-add=NET_ADMIN \ - --cap-add=SYS_MODULE \ + --cap-add=SYS_MODULE `#optional` \ -e PUID=1000 \ -e PGID=1000 \ - -e TZ=Europe/London \ + -e TZ=Etc/UTC \ -e SERVERURL=wireguard.domain.com `#optional` \ -e SERVERPORT=51820 `#optional` \ -e PEERS=1 `#optional` \ -e PEERDNS=auto `#optional` \ -e INTERNAL_SUBNET=10.13.13.0 `#optional` \ -e ALLOWEDIPS=0.0.0.0/0 `#optional` \ + -e PERSISTENTKEEPALIVE_PEERS= `#optional` \ + -e LOG_CONFS=true `#optional` \ -p 51820:51820/udp \ -v /path/to/appdata/config:/config \ - -v /lib/modules:/lib/modules \ + -v /lib/modules:/lib/modules `#optional` \ --sysctl="net.ipv4.conf.all.src_valid_mark=1" \ --restart unless-stopped \ - ghcr.io/linuxserver/wireguard -``` + lscr.io/linuxserver/wireguard:latest +``` ## Parameters @@ -128,24 +204,30 @@ Container images are configured using parameters passed at runtime (such as thos | `-p 51820/udp` | wireguard port | | `-e PUID=1000` | for UserID - see below for explanation | | `-e PGID=1000` | for GroupID - see below for explanation | -| `-e TZ=Europe/London` | Specify a timezone to use EG Europe/London | +| `-e TZ=Etc/UTC` | specify a timezone to use, see this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). | | `-e SERVERURL=wireguard.domain.com` | External IP or domain name for docker host. Used in server mode. If set to `auto`, the container will try to determine and set the external IP automatically | | `-e SERVERPORT=51820` | External port for docker host. Used in server mode. | -| `-e PEERS=1` | Number of peers to create confs for. Required for server mode. Can be a list of names too: myPC,myPhone,myTablet... | +| `-e PEERS=1` | Number of peers to create confs for. Required for server mode. Can also be a list of names: `myPC,myPhone,myTablet` (alphanumeric only) | | `-e PEERDNS=auto` | DNS server set in peer/client configs (can be set as `8.8.8.8`). Used in server mode. Defaults to `auto`, which uses wireguard docker host's DNS via included CoreDNS forward. | | `-e INTERNAL_SUBNET=10.13.13.0` | Internal subnet for the wireguard and server and peers (only change if it clashes). Used in server mode. | | `-e ALLOWEDIPS=0.0.0.0/0` | The IPs/Ranges that the peers will be able to reach using the VPN connection. If not specified the default value is: '0.0.0.0/0, ::0/0' This will cause ALL traffic to route through the VPN, if you want split tunneling, set this to only the IPs you would like to use the tunnel AND the ip of the server's WG ip, such as 10.13.13.1. | +| `-e PERSISTENTKEEPALIVE_PEERS=` | Set to `all` or a list of comma separated peers (ie. `1,4,laptop`) for the wireguard server to send keepalive packets to listed peers every 25 seconds. Useful if server is accessed via domain name and has dynamic IP. Used only in server mode. | +| `-e LOG_CONFS=true` | Generated QR codes will be displayed in the docker log. Set to `false` to skip log output. | | `-v /config` | Contains all relevant configuration files. | -| `-v /lib/modules` | Maps host's modules folder. | +| `-v /lib/modules` | Host kernel modules for situations where they're not already loaded. | | `--sysctl=` | Required for client mode. | +### Portainer notice + +This image utilises `cap_add` or `sysctl` to work properly. This is not implemented properly in some versions of Portainer, thus this image may not work if deployed through Portainer. + ## Environment variables from files (Docker secrets) You can set any environment variable from a file by using a special prepend `FILE__`. As an example: -``` +```bash -e FILE__PASSWORD=/run/secrets/mysecretpassword ``` @@ -164,68 +246,17 @@ Ensure any volume directories on the host are owned by the same user you specify In this instance `PUID=1000` and `PGID=1000`, to find yours use `id user` as below: -``` +```bash $ id username uid=1000(dockeruser) gid=1000(dockergroup) groups=1000(dockergroup) ``` - -  -## Application Setup - -This image is designed for Ubuntu and Debian based systems mainly (it works on some others, but ymmv). During container start, it will first check if the wireguard module is already installed and loaded. If not, it will then check if the kernel headers are already installed (in `/usr/src`) and if not, attempt to download the necessary kernel headers from the ubuntu/debian/raspbian repos; then will compile and install the kernel module. - -If you're on a debian/ubuntu based host with a custom or downstream distro provided kernel (ie. Pop!_OS), the container won't be able to install the kernel headers from the regular ubuntu and debian repos. In those cases, you can try installing the headers on the host via `sudo apt install linux-headers-$(uname -r)` (if distro version) and then add a volume mapping for `/usr/src:/usr/src`, or if custom built, map the location of the existing headers to allow the container to use host installed headers to build the kernel module (tested successful on Pop!_OS, ymmv). - -With regards to arm32/64 devices, Raspberry Pi 2-4 running the [official ubuntu images prior to focal](https://ubuntu.com/download/raspberry-pi) or Raspbian Buster are supported out of the box. For all other devices and OSes, you can try installing the kernel headers on the host, and mapping `/usr/src:/usr/src` and it may just work (no guarantees). - -This can be run as a server or a client, based on the parameters used. - -## Server Mode -If the environment variable `PEERS` is set to a number or a list of strings separated by comma, the container will run in server mode and the necessary server and peer/client confs will be generated. The peer/client config qr codes will be output in the docker log. They will also be saved in text and png format under `/config/peerX` in case `PEERS` is a variable and an integer or `/config/peer_X` in case a list of names was provided instead of an integer. - -Variables `SERVERURL`, `SERVERPORT`, `INTERNAL_SUBNET` and `PEERDNS` are optional variables used for server mode. Any changes to these environment variables will trigger regeneration of server and peer confs. Peer/client confs will be recreated with existing private/public keys. Delete the peer folders for the keys to be recreated along with the confs. - -To add more peers/clients later on, you increment the `PEERS` environment variable or add more elements to the list and recreate the container. - -To display the QR codes of active peers again, you can use the following command and list the peer numbers as arguments: `docker exec -it wireguard /app/show-peer 1 4 5` or `docker exec -it wireguard /app/show-peer myPC myPhone myTablet` (Keep in mind that the QR codes are also stored as PNGs in the config folder). - -The templates used for server and peer confs are saved under `/config/templates`. Advanced users can modify these templates and force conf generation by deleting `/config/wg0.conf` and restarting the container. - -## Client Mode -Do not set the `PEERS` environment variable. Drop your client conf into the config folder as `/config/wg0.conf` and start the container. - -If you get IPv6 related errors in the log and connection cannot be established, edit the `AllowedIPs` line in your peer/client wg0.conf to include only `0.0.0.0/0` and not `::/0`; and restart the container. - -## Road warriors, roaming and returning home -If you plan to use Wireguard both remotely and locally, say on your mobile phone, you will need to consider routing. Most firewalls will not route ports forwarded on your WAN interface correctly to the LAN out of the box. This means that when you return home, even though you can see the Wireguard server, the return packets will probably get lost. - -This is not a Wireguard specific issue and the two generally accepted solutions are NAT reflection (setting your edge router/firewall up in such a way as it translates internal packets correctly) or split horizon DNS (setting your internal DNS to return the private rather than public IP when connecting locally). - -Both of these approaches have positives and negatives however their setup is out of scope for this document as everyone's network layout and equipment will be different. - -## Maintaining local access to attached services - -** Note: This is not a supported configuration by Linuxserver.io - use at your own risk. - -When routing via Wireguard from another container using the `service` option in docker, you might lose access to the containers webUI locally. To avoid this, exclude the docker subnet from being routed via Wireguard by modifying your `wg0.conf` like so (modifying the subnets as you require): - - ``` - [Interface] - PrivateKey = <private key> - Address = 9.8.7.6/32 - DNS = 8.8.8.8 - PostUp = DROUTE=$(ip route | grep default | awk '{print $3}'); HOMENET=192.168.0.0/16; HOMENET2=10.0.0.0/8; HOMENET3=172.16.0.0/12; ip route add $HOMENET3 via $DROUTE;ip route add $HOMENET2 via $DROUTE; ip route add $HOMENET via $DROUTE;iptables -I OUTPUT -d $HOMENET -j ACCEPT;iptables -A OUTPUT -d $HOMENET2 -j ACCEPT; iptables -A OUTPUT -d $HOMENET3 -j ACCEPT; iptables -A OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT - PreDown = HOMENET=192.168.0.0/16; HOMENET2=10.0.0.0/8; HOMENET3=172.16.0.0/12; ip route del $HOMENET3 via $DROUTE;ip route del $HOMENET2 via $DROUTE; ip route del $HOMENET via $DROUTE; iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT; iptables -D OUTPUT -d $HOMENET -j ACCEPT; iptables -D OUTPUT -d $HOMENET2 -j ACCEPT; iptables -D OUTPUT -d $HOMENET3 -j ACCEPT - ``` - - ## Docker Mods + [![Docker Mods](https://img.shields.io/badge/dynamic/yaml?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=wireguard&query=%24.mods%5B%27wireguard%27%5D.mod_count&url=https%3A%2F%2Fraw.githubusercontent.com%2Flinuxserver%2Fdocker-mods%2Fmaster%2Fmod-list.yml)](https://mods.linuxserver.io/?mod=wireguard "view available mods for this container.") [![Docker Universal Mods](https://img.shields.io/badge/dynamic/yaml?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=universal&query=%24.mods%5B%27universal%27%5D.mod_count&url=https%3A%2F%2Fraw.githubusercontent.com%2Flinuxserver%2Fdocker-mods%2Fmaster%2Fmod-list.yml)](https://mods.linuxserver.io/?mod=universal "view available universal mods.") We publish various [Docker Mods](https://github.com/linuxserver/docker-mods) to enable additional functionality within the containers. The list of Mods available for this image (if any) as well as universal mods that can be applied to any one of our images can be accessed via the dynamic badges above. - ## Support Info * Shell access whilst the container is running: `docker exec -it wireguard /bin/bash` @@ -233,7 +264,7 @@ We publish various [Docker Mods](https://github.com/linuxserver/docker-mods) to * container version number * `docker inspect -f '{{ index .Config.Labels "build_version" }}' wireguard` * image version number - * `docker inspect -f '{{ index .Config.Labels "build_version" }}' ghcr.io/linuxserver/wireguard` + * `docker inspect -f '{{ index .Config.Labels "build_version" }}' lscr.io/linuxserver/wireguard:latest` ## Updating Info @@ -242,6 +273,7 @@ Most of our images are static, versioned, and require an image update and contai Below are the instructions for updating containers: ### Via Docker Compose + * Update all images: `docker-compose pull` * or update a single image: `docker-compose pull wireguard` * Let compose update all containers as necessary: `docker-compose up -d` @@ -249,41 +281,48 @@ Below are the instructions for updating containers: * You can also remove the old dangling images: `docker image prune` ### Via Docker Run -* Update the image: `docker pull ghcr.io/linuxserver/wireguard` + +* Update the image: `docker pull lscr.io/linuxserver/wireguard:latest` * Stop the running container: `docker stop wireguard` * Delete the container: `docker rm wireguard` * Recreate a new container with the same docker run parameters as instructed above (if mapped correctly to a host folder, your `/config` folder and settings will be preserved) * You can also remove the old dangling images: `docker image prune` ### Via Watchtower auto-updater (only use if you don't remember the original parameters) + * Pull the latest image at its tag and replace it with the same env variables in one run: - ``` + + ```bash docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --run-once wireguard ``` + * You can also remove the old dangling images: `docker image prune` **Note:** We do not endorse the use of Watchtower as a solution to automated updates of existing Docker containers. In fact we generally discourage automated updates. However, this is a useful tool for one-time manual updates of containers where you have forgotten the original parameters. In the long term, we highly recommend using [Docker Compose](https://docs.linuxserver.io/general/docker-compose). ### Image Update Notifications - Diun (Docker Image Update Notifier) + * We recommend [Diun](https://crazymax.dev/diun/) for update notifications. Other tools that automatically update containers unattended are not recommended or supported. ## Building locally If you want to make local modifications to these images for development purposes or just to customize the logic: -``` + +```bash git clone https://github.com/linuxserver/docker-wireguard.git cd docker-wireguard docker build \ --no-cache \ --pull \ - -t ghcr.io/linuxserver/wireguard:latest . + -t lscr.io/linuxserver/wireguard:latest . ``` The ARM variants can be built on x86_64 hardware using `multiarch/qemu-user-static` -``` + +```bash docker run --rm --privileged multiarch/qemu-user-static:register --reset ``` @@ -291,6 +330,19 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **28.06.23:** - Rebase master to Alpine 3.18 again. +* **26.06.23:** - Revert master to Alpine 3.17, due to issue with openresolv. +* **24.06.23:** - Rebase master to Alpine 3.18, deprecate armhf as per [https://www.linuxserver.io/armhf](https://www.linuxserver.io/armhf). +* **26.04.23:** - Rework branches. Swap alpine and ubuntu builds. +* **29.01.23:** - Rebase to alpine 3.17. +* **10.01.23:** - Add new var to add `PersistentKeepalive` to server config for select peers to survive server IP changes when domain name is used. +* **26.10.22:** - Better handle unsupported peer names. Improve logging. +* **12.10.22:** - Add Alpine branch. Optimize wg and coredns services. +* **04.10.22:** - Rebase to Jammy. Upgrade to s6v3. +* **16.05.22:** - Improve NAT handling in server mode when multiple ethernet devices are present. +* **23.04.22:** - Add pre-shared key support. Automatically added to all new peer confs generated, existing ones are left without to ensure no breaking changes. +* **10.04.22:** - Rebase to Ubuntu Focal. Add `LOG_CONFS` env var. Remove deprecated `add-peer` command. +* **28.10.21:** - Add site-to-site vpn support. * **11.02.21:** - Fix bug related to changing internal subnet and named peer confs not updating. * **06.10.20:** - Disable CoreDNS in client mode, or if port 53 is already in use in server mode. * **04.10.20:** - Allow to specify a list of names as PEERS and add ALLOWEDIPS environment variable. Also, add peer name/id to each one of the peer sections in wg0.conf. Important: Existing users need to delete `/config/templates/peer.conf` and restart diff --git a/api/src/index.ts b/api/src/index.ts index 9e24ac3d..c8e0b895 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -8,7 +8,10 @@ import { const port = process.env.SERVER_PORT || 80; const app = express(); -app.use(cors()); +const corsOptions = { + origin: "http://my.dappnode" +} +app.use(cors(corsOptions)); // - remote: '/dappnode_admin' // - remote qr: '/dappnode_admin?qr' diff --git a/package_versions.txt b/package_versions.txt index cdd75fa0..7290cf9f 100755 --- a/package_versions.txt +++ b/package_versions.txt @@ -1,216 +1,214 @@ -adduser3.116ubuntu1 -apt1.6.12ubuntu0.2 -apt-utils1.6.12ubuntu0.2 -base-files10.1ubuntu2.10 -base-passwd3.5.44 -bash4.4.18-2ubuntu1.2 -bc1.07.1-2 -binutils2.30-21ubuntu1~18.04.5 -binutils-common2.30-21ubuntu1~18.04.5 -binutils-x86-64-linux-gnu2.30-21ubuntu1~18.04.5 -bsdutils1:2.31.1-0.4ubuntu3.7 -build-essential12.4ubuntu1 -bzip21.0.6-8.1ubuntu0.2 -ca-certificates20210119~18.04.1 -coreutils8.28-1ubuntu1 -cpp4:7.4.0-1ubuntu2.3 -cpp-77.5.0-3ubuntu1~18.04 -curl7.58.0-2ubuntu3.12 -dash0.5.8-2.10 -debconf1.5.66ubuntu1 -debianutils4.8.4 -diffutils1:3.6-1 -dirmngr2.2.4-1ubuntu1.4 -dkms2.3-3ubuntu9.7 -dpkg1.19.0.5ubuntu2.3 -dpkg-dev1.19.0.5ubuntu2.3 -e2fsprogs1.44.1-1ubuntu1.3 -fdisk2.31.1-0.4ubuntu3.7 -findutils4.6.0+git+20170828-2 -g++4:7.4.0-1ubuntu2.3 -g++-77.5.0-3ubuntu1~18.04 -gcc4:7.4.0-1ubuntu2.3 -gcc-77.5.0-3ubuntu1~18.04 -gcc-7-base7.5.0-3ubuntu1~18.04 -gcc-8-base8.4.0-1ubuntu1~18.04 -git1:2.17.1-1ubuntu0.8 -git-man1:2.17.1-1ubuntu0.8 -gnupg2.2.4-1ubuntu1.4 -gnupg-l10n2.2.4-1ubuntu1.4 -gnupg-utils2.2.4-1ubuntu1.4 -gpg2.2.4-1ubuntu1.4 -gpg-agent2.2.4-1ubuntu1.4 -gpgconf2.2.4-1ubuntu1.4 -gpgsm2.2.4-1ubuntu1.4 -gpgv2.2.4-1ubuntu1.4 -gpg-wks-client2.2.4-1ubuntu1.4 -gpg-wks-server2.2.4-1ubuntu1.4 -grep3.1-2build1 -gzip1.6-5ubuntu1 -hostname3.20 -ifupdown0.8.17ubuntu1.1 -init-system-helpers1.51 -iproute24.15.0-2ubuntu1.3 -iptables1.6.1-2ubuntu2 -iputils-ping3:20161105-1ubuntu3 -jq1.5+dfsg-2 -kmod24-1ubuntu3.5 -krb5-locales1.16-2ubuntu0.2 -libacl12.2.52-3build1 -libapt-inst2.01.6.12ubuntu0.2 -libapt-pkg5.01.6.12ubuntu0.2 -libasan47.5.0-3ubuntu1~18.04 -libasn1-8-heimdal7.5.0+dfsg-1 -libassuan02.5.1-2 -libatomic18.4.0-1ubuntu1~18.04 -libattr11:2.4.47-2build1 -libaudit11:2.8.2-1ubuntu1.1 -libaudit-common1:2.8.2-1ubuntu1.1 -libbinutils2.30-21ubuntu1~18.04.5 -libblkid12.31.1-0.4ubuntu3.7 -libbz2-1.01.0.6-8.1ubuntu0.2 -libc62.27-3ubuntu1.4 -libc6-dev2.27-3ubuntu1.4 -libcap21:2.25-1.2 -libcap-ng00.7.7-3.1 -libc-bin2.27-3ubuntu1.4 -libcc1-08.4.0-1ubuntu1~18.04 -libc-dev-bin2.27-3ubuntu1.4 -libcilkrts57.5.0-3ubuntu1~18.04 -libcom-err21.44.1-1ubuntu1.3 -libcurl3-gnutls7.58.0-2ubuntu3.12 -libcurl47.58.0-2ubuntu3.12 -libdb5.35.3.28-13.1ubuntu1.1 -libdebconfclient00.213ubuntu1 -libdpkg-perl1.19.0.5ubuntu2.3 -libelf10.170-0.4ubuntu0.1 -libelf-dev0.170-0.4ubuntu0.1 -liberror-perl0.17025-1 -libexpat12.2.5-3ubuntu0.2 -libext2fs21.44.1-1ubuntu1.3 -libfdisk12.31.1-0.4ubuntu3.7 -libffi63.2.1-8 -libgcc11:8.4.0-1ubuntu1~18.04 -libgcc-7-dev7.5.0-3ubuntu1~18.04 -libgcrypt201.8.1-4ubuntu1.2 -libgdbm51.14.1-6 -libgdbm-compat41.14.1-6 -libglib2.0-02.56.4-0ubuntu0.18.04.8 -libgmp102:6.1.2+dfsg-2 -libgnutls303.5.18-1ubuntu1.4 -libgomp18.4.0-1ubuntu1~18.04 -libgpg-error01.27-6 -libgssapi3-heimdal7.5.0+dfsg-1 -libgssapi-krb5-21.16-2ubuntu0.2 -libhcrypto4-heimdal7.5.0+dfsg-1 -libheimbase1-heimdal7.5.0+dfsg-1 -libheimntlm0-heimdal7.5.0+dfsg-1 -libhogweed43.4-1 -libhx509-5-heimdal7.5.0+dfsg-1 -libidn111.33-2.1ubuntu1.2 -libidn2-02.0.4-1.1ubuntu0.2 -libip4tc01.6.1-2ubuntu2 -libip6tc01.6.1-2ubuntu2 -libiptc01.6.1-2ubuntu2 -libisl190.19-1 -libitm18.4.0-1ubuntu1~18.04 -libjq11.5+dfsg-2 -libk5crypto31.16-2ubuntu0.2 -libkeyutils11.5.9-9.2ubuntu2 -libkmod224-1ubuntu3.5 -libkrb5-26-heimdal7.5.0+dfsg-1 -libkrb5-31.16-2ubuntu0.2 -libkrb5support01.16-2ubuntu0.2 -libksba81.3.5-2 -libldap-2.4-22.4.45+dfsg-1ubuntu1.10 -libldap-common2.4.45+dfsg-1ubuntu1.10 -liblsan08.4.0-1ubuntu1~18.04 -liblz4-10.0~r131-2ubuntu3 -liblzma55.2.2-1.3 -libmnl01.0.4-2 -libmount12.31.1-0.4ubuntu3.7 -libmpc31.1.0-1 -libmpfr64.0.1-1 -libmpx28.4.0-1ubuntu1~18.04 -libncurses56.1-1ubuntu1.18.04 -libncursesw56.1-1ubuntu1.18.04 -libnetfilter-conntrack31.0.6-2 -libnettle63.4-1 -libnfnetlink01.0.1-3 -libnghttp2-141.30.0-1ubuntu1 -libnpth01.5-3 -libonig46.7.0-1 -libp11-kit00.23.9-2ubuntu0.1 -libpam0g1.1.8-3.6ubuntu2.18.04.2 -libpam-modules1.1.8-3.6ubuntu2.18.04.2 -libpam-modules-bin1.1.8-3.6ubuntu2.18.04.2 -libpam-runtime1.1.8-3.6ubuntu2.18.04.2 -libpcre32:8.39-9 -libperl5.265.26.1-6ubuntu0.5 -libpng16-161.6.34-1ubuntu0.18.04.2 -libprocps62:3.3.12-3ubuntu1.2 -libpsl50.19.1-5build1 -libqrencode33.4.4-1build1 -libquadmath08.4.0-1ubuntu1~18.04 -libreadline77.0-3 -libroken18-heimdal7.5.0+dfsg-1 -librtmp12.4+20151223.gitfa8646d.1-1 -libsasl2-22.1.27~101-g0780600+dfsg-3ubuntu2.3 -libsasl2-modules2.1.27~101-g0780600+dfsg-3ubuntu2.3 -libsasl2-modules-db2.1.27~101-g0780600+dfsg-3ubuntu2.3 -libseccomp22.4.3-1ubuntu3.18.04.3 -libselinux12.7-2build2 -libsemanage12.7-2build2 -libsemanage-common2.7-2build2 -libsepol12.7-1 -libsmartcols12.31.1-0.4ubuntu3.7 -libsqlite3-03.22.0-1ubuntu0.4 -libss21.44.1-1ubuntu1.3 -libssl1.11.1.1-1ubuntu2.1~18.04.8 -libstdc++68.4.0-1ubuntu1~18.04 -libstdc++-7-dev7.5.0-3ubuntu1~18.04 -libsystemd0237-3ubuntu10.44 -libtasn1-64.13-2 -libtinfo56.1-1ubuntu1.18.04 -libtsan08.4.0-1ubuntu1~18.04 -libubsan07.5.0-3ubuntu1~18.04 -libudev1237-3ubuntu10.44 -libunistring20.9.9-0ubuntu2 -libuuid12.31.1-0.4ubuntu3.7 -libwind0-heimdal7.5.0+dfsg-1 -libxtables121.6.1-2ubuntu2 -libzstd11.3.3+dfsg-2ubuntu1.2 -linux-libc-dev4.15.0-139.143 -locales2.27-3ubuntu1.4 -login1:4.5-1ubuntu2 -lsb-base9.20170808ubuntu1 -make4.1-9.1ubuntu1 -mawk1.3.3-17ubuntu3 -mount2.31.1-0.4ubuntu3.7 -multiarch-support2.27-3ubuntu1.4 -ncurses-base6.1-1ubuntu1.18.04 -ncurses-bin6.1-1ubuntu1.18.04 -net-tools1.60+git20161116.90da8a0-1ubuntu1 -openresolv3.8.0-1 -openssl1.1.1-1ubuntu2.1~18.04.8 -passwd1:4.5-1ubuntu2 -patch2.7.6-2ubuntu1.1 -perl5.26.1-6ubuntu0.5 -perl-base5.26.1-6ubuntu0.5 -perl-modules-5.265.26.1-6ubuntu0.5 -pinentry-curses1.1.0-1 -pkg-config0.29.1-0ubuntu2 -procps2:3.3.12-3ubuntu1.2 -publicsuffix20180223.1310-1 -qrencode3.4.4-1build1 -readline-common7.0-3 -sed4.4-2 -sensible-utils0.0.12 -sysvinit-utils2.88dsf-59.10ubuntu1 -tar1.29b-2ubuntu0.2 -tzdata2021a-0ubuntu0.18.04 -ubuntu-keyring2018.09.18.1~18.04.0 -util-linux2.31.1-0.4ubuntu3.7 -xz-utils5.2.2-1.3 -zlib1g1:1.2.11.dfsg-0ubuntu2 -zlib1g-dev1:1.2.11.dfsg-0ubuntu2 +NAME VERSION TYPE +alpine-baselayout 3.4.3-r1 apk +alpine-baselayout-data 3.4.3-r1 apk +alpine-keys 2.4-r1 apk +alpine-release 3.18.4-r0 apk +apk-tools 2.14.0-r2 apk +bash 5.2.15-r5 apk +bc 1.07.1-r4 apk +brotli-libs 1.0.9-r14 apk +busybox 1.36.1-r2 apk +busybox-binsh 1.36.1-r2 apk +ca-certificates 20230506-r0 apk +ca-certificates-bundle 20230506-r0 apk +cloud.google.com/go/compute/metadata v0.2.3 go-module +coredns 1.10.1-r6 apk +coreutils 9.3-r1 apk +curl 8.3.0-r0 apk +gdbm 1.23-r1 apk +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible go-module +github.com/Azure/go-autorest/autorest v0.11.28 go-module +github.com/Azure/go-autorest/autorest/adal v0.9.18 go-module +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 go-module +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 go-module +github.com/Azure/go-autorest/autorest/date v0.3.0 go-module +github.com/Azure/go-autorest/autorest/to v0.2.0 go-module +github.com/Azure/go-autorest/logger v0.2.1 go-module +github.com/Azure/go-autorest/tracing v0.6.0 go-module +github.com/DataDog/datadog-agent/pkg/obfuscate v0.0.0-20211129110424-6491aa3bf583 go-module +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.42.0-rc.1 go-module +github.com/DataDog/datadog-go v4.8.2+incompatible go-module +github.com/DataDog/datadog-go/v5 v5.0.2 go-module +github.com/DataDog/go-tuf v0.3.0--fix-localmeta-fork go-module +github.com/DataDog/sketches-go v1.2.1 go-module +github.com/apparentlymart/go-cidr v1.1.0 go-module +github.com/aws/aws-sdk-go v1.44.194 go-module +github.com/beorn7/perks v1.0.1 go-module +github.com/cespare/xxhash/v2 v2.1.2 go-module +github.com/coredns/caddy v1.1.1 go-module +github.com/coredns/coredns (devel) go-module +github.com/coredns/unbound v0.0.7 go-module +github.com/coreos/go-semver v0.3.0 go-module +github.com/coreos/go-systemd/v22 v22.3.2 go-module +github.com/davecgh/go-spew v1.1.1 go-module +github.com/dgraph-io/ristretto v0.1.0 go-module +github.com/dimchansky/utfbom v1.1.1 go-module +github.com/dnstap/golang-dnstap v0.4.0 go-module +github.com/dustin/go-humanize v1.0.0 go-module +github.com/emicklei/go-restful/v3 v3.9.0 go-module +github.com/farsightsec/golang-framestream v0.3.0 go-module +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 go-module +github.com/go-logr/logr v1.2.3 go-module +github.com/go-openapi/jsonpointer v0.19.5 go-module +github.com/go-openapi/jsonreference v0.20.0 go-module +github.com/go-openapi/swag v0.19.14 go-module +github.com/gogo/protobuf v1.3.2 go-module +github.com/golang-jwt/jwt/v4 v4.2.0 go-module +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b go-module +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da go-module +github.com/golang/protobuf v1.5.2 go-module +github.com/google/gnostic v0.5.7-v3refs go-module +github.com/google/go-cmp v0.5.9 go-module +github.com/google/gofuzz v1.2.0 go-module +github.com/google/uuid v1.3.0 go-module +github.com/googleapis/enterprise-certificate-proxy v0.2.1 go-module +github.com/googleapis/gax-go/v2 v2.7.0 go-module +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 go-module +github.com/imdario/mergo v0.3.12 go-module +github.com/infobloxopen/go-trees v0.0.0-20200715205103-96a057b8dfb9 go-module +github.com/jmespath/go-jmespath v0.4.0 go-module +github.com/josharian/intern v1.0.0 go-module +github.com/json-iterator/go v1.1.12 go-module +github.com/mailru/easyjson v0.7.7 go-module +github.com/matttproud/golang_protobuf_extensions v1.0.4 go-module +github.com/miekg/coredns-git v0.0.0-20210209133530-8360cff99ce7 go-module +github.com/miekg/dns v1.1.50 go-module +github.com/miekg/unbound v0.0.0-20210309082708-dbeefb4cdb29 go-module +github.com/mitchellh/go-homedir v1.1.0 go-module +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd go-module +github.com/modern-go/reflect2 v1.0.2 go-module +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 go-module +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 go-module +github.com/opentracing/opentracing-go v1.2.0 go-module +github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0 go-module +github.com/openzipkin/zipkin-go v0.4.1 go-module +github.com/oschwald/geoip2-golang v1.8.0 go-module +github.com/oschwald/maxminddb-golang v1.10.0 go-module +github.com/oz123/coredns-netbox-plugin v0.4.0 go-module +github.com/philhofer/fwd v1.1.1 go-module +github.com/pkg/errors v0.9.1 go-module +github.com/prometheus/client_golang v1.14.0 go-module +github.com/prometheus/client_model v0.3.0 go-module +github.com/prometheus/common v0.39.0 go-module +github.com/prometheus/procfs v0.8.0 go-module +github.com/secure-systems-lab/go-securesystemslib v0.4.0 go-module +github.com/spf13/pflag v1.0.5 go-module +github.com/tinylib/msgp v1.1.6 go-module +gmp 6.2.1-r3 apk +gnupg 2.4.3-r0 apk +gnupg-dirmngr 2.4.3-r0 apk +gnupg-gpgconf 2.4.3-r0 apk +gnupg-keyboxd 2.4.3-r0 apk +gnupg-utils 2.4.3-r0 apk +gnupg-wks-client 2.4.3-r0 apk +gnutls 3.8.0-r2 apk +go.etcd.io/etcd/api/v3 v3.5.7 go-module +go.etcd.io/etcd/client/pkg/v3 v3.5.7 go-module +go.etcd.io/etcd/client/v3 v3.5.7 go-module +go.opencensus.io v0.24.0 go-module +go.uber.org/atomic v1.9.0 go-module +go.uber.org/multierr v1.6.0 go-module +go.uber.org/zap v1.17.0 go-module +golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2 go-module +golang.org/x/net v0.4.0 go-module +golang.org/x/oauth2 v0.3.0 go-module +golang.org/x/sys v0.4.0 go-module +golang.org/x/term v0.3.0 go-module +golang.org/x/text v0.5.0 go-module +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 go-module +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 go-module +google.golang.org/api v0.109.0 go-module +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef go-module +google.golang.org/grpc v1.52.3 go-module +google.golang.org/protobuf v1.28.1 go-module +gopkg.in/DataDog/dd-trace-go.v1 v1.47.0 go-module +gopkg.in/inf.v0 v0.9.1 go-module +gopkg.in/yaml.v2 v2.4.0 go-module +gopkg.in/yaml.v3 v3.0.1 go-module +gpg 2.4.3-r0 apk +gpg-agent 2.4.3-r0 apk +gpg-wks-server 2.4.3-r0 apk +gpgsm 2.4.3-r0 apk +gpgv 2.4.3-r0 apk +grep 3.10-r1 apk +ip6tables 1.8.9-r2 apk +iproute2 6.3.0-r0 apk +iproute2-minimal 6.3.0-r0 apk +iproute2-ss 6.3.0-r0 apk +iproute2-tc 6.3.0-r0 apk +iptables 1.8.9-r2 apk +iputils 20221126-r2 apk +iputils-arping 20221126-r2 apk +iputils-clockdiff 20221126-r2 apk +iputils-ping 20221126-r2 apk +iputils-tracepath 20221126-r2 apk +jq 1.6-r3 apk +k8s.io/api v0.26.1 go-module +k8s.io/apimachinery v0.26.1 go-module +k8s.io/client-go v0.26.1 go-module +k8s.io/klog/v2 v2.90.0 go-module +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 go-module +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d go-module +libacl 2.3.1-r3 apk +libassuan 2.5.6-r0 apk +libattr 2.5.1-r4 apk +libbsd 0.11.7-r1 apk +libbz2 1.0.8-r5 apk +libc-utils 0.7.2-r5 apk +libcap-utils 2.69-r0 apk +libcap2 2.69-r0 apk +libcrypto3 3.1.3-r0 apk +libcurl 8.3.0-r0 apk +libelf 0.189-r2 apk +libevent 2.1.12-r6 apk +libffi 3.4.4-r2 apk +libgcrypt 1.10.2-r1 apk +libgpg-error 1.47-r1 apk +libidn2 2.3.4-r1 apk +libintl 0.21.1-r7 apk +libksba 1.6.4-r0 apk +libldap 2.6.5-r0 apk +libmd 1.0.4-r2 apk +libmnl 1.0.5-r1 apk +libncursesw 6.4_p20230506-r0 apk +libnftnl 1.2.5-r1 apk +libpng 1.6.39-r3 apk +libproc2 4.0.4-r0 apk +libqrencode 4.1.1-r1 apk +libsasl 2.1.28-r4 apk +libssl3 3.1.3-r0 apk +libtasn1 4.19.0-r1 apk +libunistring 1.1-r1 apk +linux-pam 1.5.2-r10 apk +mii-tool 2.10-r3 apk +musl 1.2.4-r1 apk +musl-fts 1.2.7-r5 apk +musl-utils 1.2.4-r1 apk +ncurses-terminfo-base 6.4_p20230506-r0 apk +net-tools 2.10-r3 apk +netcat-openbsd 1.219-r1 apk +nettle 3.8.1-r2 apk +nghttp2-libs 1.55.1-r0 apk +npth 1.6-r4 apk +oniguruma 6.9.8-r1 apk +openresolv 3.13.2-r0 apk +p11-kit 0.24.1-r2 apk +pcre2 10.42-r1 apk +perl 5.36.1-r2 apk +pinentry 1.2.1-r1 apk +procps-ng 4.0.4-r0 apk +readline 8.2.1-r1 apk +scanelf 1.3.7-r1 apk +shadow 4.13-r4 apk +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 go-module +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 go-module +sigs.k8s.io/yaml v1.3.0 go-module +skalibs 2.13.1.1-r1 apk +sqlite-libs 3.41.2-r2 apk +ssl_client 1.36.1-r2 apk +tzdata 2023c-r1 apk +unbound-libs 1.17.1-r1 apk +utmps-libs 0.1.2.1-r1 apk +xz-libs 5.4.3-r0 apk +zlib 1.2.13-r1 apk +zstd-libs 1.5.5-r4 apk diff --git a/readme-vars.yml b/readme-vars.yml index fb5fa2fb..60e772c2 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -11,13 +11,12 @@ project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_ available_architectures: - { arch: "{{ arch_x86_64 }}", tag: "amd64-latest"} - { arch: "{{ arch_arm64 }}", tag: "arm64v8-latest"} - - { arch: "{{ arch_armhf }}", tag: "arm32v7-latest"} # development version -development_versions: false +development_versions: true development_versions_items: - - { tag: "latest", desc: "Stable releases" } - - { tag: "development", desc: "Prereleases from their GitHub" } + - { tag: "latest", desc: "Stable releases based on Alpine *without* support for compiling Wireguard modules." } + - { tag: "legacy", desc: "Stable releases with support for compiling Wireguard modules for older kernels." } # container parameters common_param_env_vars_enabled: true @@ -25,7 +24,9 @@ param_container_name: "{{ project_name }}" param_usage_include_vols: true param_volumes: - { vol_path: "/config", vol_host_path: "/path/to/appdata/config", desc: "Contains all relevant configuration files." } - - { vol_path: "/lib/modules", vol_host_path: "/lib/modules", desc: "Maps host's modules folder." } +opt_param_usage_include_vols: true +opt_param_volumes: + - { vol_path: "/lib/modules", vol_host_path: "/lib/modules", desc: "Host kernel modules for situations where they're not already loaded." } param_usage_include_ports: true param_ports: - { external_port: "51820", internal_port: "51820/udp", port_desc: "wireguard port" } @@ -35,6 +36,8 @@ param_env_vars: cap_add_param: true cap_add_param_vars: - { cap_add_var: "NET_ADMIN" } +opt_cap_add_param: true +opt_cap_add_param_vars: - { cap_add_var: "SYS_MODULE" } custom_params: - { name: "sysctl", name_compose: "sysctls", value: ["net.ipv4.conf.all.src_valid_mark=1"], desc: "Required for client mode.", array: "true" } @@ -44,10 +47,12 @@ opt_param_usage_include_env: true opt_param_env_vars: - { env_var: "SERVERURL", env_value: "wireguard.domain.com", desc: "External IP or domain name for docker host. Used in server mode. If set to `auto`, the container will try to determine and set the external IP automatically"} - { env_var: "SERVERPORT", env_value: "51820", desc: "External port for docker host. Used in server mode."} - - { env_var: "PEERS", env_value: "1", desc: "Number of peers to create confs for. Required for server mode. Can be a list of names too: myPC,myPhone,myTablet..."} + - { env_var: "PEERS", env_value: "1", desc: "Number of peers to create confs for. Required for server mode. Can also be a list of names: `myPC,myPhone,myTablet` (alphanumeric only)"} - { env_var: "PEERDNS", env_value: "auto", desc: "DNS server set in peer/client configs (can be set as `8.8.8.8`). Used in server mode. Defaults to `auto`, which uses wireguard docker host's DNS via included CoreDNS forward."} - { env_var: "INTERNAL_SUBNET", env_value: "10.13.13.0", desc: "Internal subnet for the wireguard and server and peers (only change if it clashes). Used in server mode."} - { env_var: "ALLOWEDIPS", env_value: "0.0.0.0/0", desc: "The IPs/Ranges that the peers will be able to reach using the VPN connection. If not specified the default value is: '0.0.0.0/0, ::0/0' This will cause ALL traffic to route through the VPN, if you want split tunneling, set this to only the IPs you would like to use the tunnel AND the ip of the server's WG ip, such as 10.13.13.1."} + - { env_var: "PERSISTENTKEEPALIVE_PEERS", env_value: "", desc: "Set to `all` or a list of comma separated peers (ie. `1,4,laptop`) for the wireguard server to send keepalive packets to listed peers every 25 seconds. Useful if server is accessed via domain name and has dynamic IP. Used only in server mode."} + - { env_var: "LOG_CONFS", env_value: "true", desc: "Generated QR codes will be displayed in the docker log. Set to `false` to skip log output."} optional_block_1: false optional_block_1_items: "" @@ -55,35 +60,38 @@ optional_block_1_items: "" # application setup block app_setup_block_enabled: true app_setup_block: | - This image is designed for Ubuntu and Debian based systems mainly (it works on some others, but ymmv). During container start, it will first check if the wireguard module is already installed and loaded. If not, it will then check if the kernel headers are already installed (in `/usr/src`) and if not, attempt to download the necessary kernel headers from the ubuntu/debian/raspbian repos; then will compile and install the kernel module. + During container start, it will first check if the wireguard module is already installed and loaded. Kernels newer than 5.6 generally have the wireguard module built-in (along with some older custom kernels). However, the module may not be enabled. Make sure it is enabled prior to starting the container. - If you're on a debian/ubuntu based host with a custom or downstream distro provided kernel (ie. Pop!_OS), the container won't be able to install the kernel headers from the regular ubuntu and debian repos. In those cases, you can try installing the headers on the host via `sudo apt install linux-headers-$(uname -r)` (if distro version) and then add a volume mapping for `/usr/src:/usr/src`, or if custom built, map the location of the existing headers to allow the container to use host installed headers to build the kernel module (tested successful on Pop!_OS, ymmv). + This can be run as a server or a client, based on the parameters used. - With regards to arm32/64 devices, Raspberry Pi 2-4 running the [official ubuntu images prior to focal](https://ubuntu.com/download/raspberry-pi) or Raspbian Buster are supported out of the box. For all other devices and OSes, you can try installing the kernel headers on the host, and mapping `/usr/src:/usr/src` and it may just work (no guarantees). + ## Note on iptables - This can be run as a server or a client, based on the parameters used. + Some hosts may not load the iptables kernel modules by default. In order for the container to be able to load them, you need to assign the `SYS_MODULE` capability and add the optional `/lib/modules` volume mount. Alternatively you can `modprobe` them from the host before starting the container. ## Server Mode - If the environment variable `PEERS` is set to a number or a list of strings separated by comma, the container will run in server mode and the necessary server and peer/client confs will be generated. The peer/client config qr codes will be output in the docker log. They will also be saved in text and png format under `/config/peerX` in case `PEERS` is a variable and an integer or `/config/peer_X` in case a list of names was provided instead of an integer. - - Variables `SERVERURL`, `SERVERPORT`, `INTERNAL_SUBNET` and `PEERDNS` are optional variables used for server mode. Any changes to these environment variables will trigger regeneration of server and peer confs. Peer/client confs will be recreated with existing private/public keys. Delete the peer folders for the keys to be recreated along with the confs. - + + If the environment variable `PEERS` is set to a number or a list of strings separated by comma, the container will run in server mode and the necessary server and peer/client confs will be generated. The peer/client config qr codes will be output in the docker log if `LOG_CONFS` is set to `true`. They will also be saved in text and png format under `/config/peerX` in case `PEERS` is a variable and an integer or `/config/peer_X` in case a list of names was provided instead of an integer. + + Variables `SERVERURL`, `SERVERPORT`, `INTERNAL_SUBNET`, `PEERDNS`, `INTERFACE`, `ALLOWEDIPS` and `PERSISTENTKEEPALIVE_PEERS` are optional variables used for server mode. Any changes to these environment variables will trigger regeneration of server and peer confs. Peer/client confs will be recreated with existing private/public keys. Delete the peer folders for the keys to be recreated along with the confs. + To add more peers/clients later on, you increment the `PEERS` environment variable or add more elements to the list and recreate the container. - + To display the QR codes of active peers again, you can use the following command and list the peer numbers as arguments: `docker exec -it wireguard /app/show-peer 1 4 5` or `docker exec -it wireguard /app/show-peer myPC myPhone myTablet` (Keep in mind that the QR codes are also stored as PNGs in the config folder). The templates used for server and peer confs are saved under `/config/templates`. Advanced users can modify these templates and force conf generation by deleting `/config/wg0.conf` and restarting the container. ## Client Mode - Do not set the `PEERS` environment variable. Drop your client conf into the config folder as `/config/wg0.conf` and start the container. + + Do not set the `PEERS` environment variable. Drop your client conf into the config folder as `/config/wg0.conf` and start the container. If you get IPv6 related errors in the log and connection cannot be established, edit the `AllowedIPs` line in your peer/client wg0.conf to include only `0.0.0.0/0` and not `::/0`; and restart the container. ## Road warriors, roaming and returning home + If you plan to use Wireguard both remotely and locally, say on your mobile phone, you will need to consider routing. Most firewalls will not route ports forwarded on your WAN interface correctly to the LAN out of the box. This means that when you return home, even though you can see the Wireguard server, the return packets will probably get lost. - + This is not a Wireguard specific issue and the two generally accepted solutions are NAT reflection (setting your edge router/firewall up in such a way as it translates internal packets correctly) or split horizon DNS (setting your internal DNS to return the private rather than public IP when connecting locally). - + Both of these approaches have positives and negatives however their setup is out of scope for this document as everyone's network layout and equipment will be different. ## Maintaining local access to attached services @@ -92,7 +100,7 @@ app_setup_block: | When routing via Wireguard from another container using the `service` option in docker, you might lose access to the containers webUI locally. To avoid this, exclude the docker subnet from being routed via Wireguard by modifying your `wg0.conf` like so (modifying the subnets as you require): - ``` + ```ini [Interface] PrivateKey = <private key> Address = 9.8.7.6/32 @@ -100,9 +108,37 @@ app_setup_block: | PostUp = DROUTE=$(ip route | grep default | awk '{print $3}'); HOMENET=192.168.0.0/16; HOMENET2=10.0.0.0/8; HOMENET3=172.16.0.0/12; ip route add $HOMENET3 via $DROUTE;ip route add $HOMENET2 via $DROUTE; ip route add $HOMENET via $DROUTE;iptables -I OUTPUT -d $HOMENET -j ACCEPT;iptables -A OUTPUT -d $HOMENET2 -j ACCEPT; iptables -A OUTPUT -d $HOMENET3 -j ACCEPT; iptables -A OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT PreDown = HOMENET=192.168.0.0/16; HOMENET2=10.0.0.0/8; HOMENET3=172.16.0.0/12; ip route del $HOMENET3 via $DROUTE;ip route del $HOMENET2 via $DROUTE; ip route del $HOMENET via $DROUTE; iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT; iptables -D OUTPUT -d $HOMENET -j ACCEPT; iptables -D OUTPUT -d $HOMENET2 -j ACCEPT; iptables -D OUTPUT -d $HOMENET3 -j ACCEPT ``` + + ## Site-to-site VPN + + ** Note: This is not a supported configuration by Linuxserver.io - use at your own risk. + + Site-to-site VPN in server mode requires customizing the `AllowedIPs` statement for a specific peer in `wg0.conf`. Since `wg0.conf` is autogenerated when server vars are changed, it is not recommended to edit it manually. + + In order to customize the `AllowedIPs` statement for a specific peer in `wg0.conf`, you can set an env var `SERVER_ALLOWEDIPS_PEER_<peer name or number>` to the additional subnets you'd like to add, comma separated and excluding the peer IP (ie. `"192.168.1.0/24,192.168.2.0/24"`). Replace `<peer name or number>` with either the name or number of a peer (whichever is used in the `PEERS` var). + + For instance `SERVER_ALLOWEDIPS_PEER_laptop="192.168.1.0/24,192.168.2.0/24"` will result in the wg0.conf entry `AllowedIPs = 10.13.13.2,192.168.1.0/24,192.168.2.0/24` for the peer named `laptop`. + Keep in mind that this var will only be considered when the confs are regenerated. Adding this var for an existing peer won't force a regeneration. You can delete wg0.conf and restart the container to force regeneration if necessary. + + Don't forget to set the necessary POSTUP and POSTDOWN rules in your client's peer conf for lan access. + + # changelog changelogs: + - { date: "28.06.23:", desc: "Rebase master to Alpine 3.18 again." } + - { date: "26.06.23:", desc: "Revert master to Alpine 3.17, due to issue with openresolv." } + - { date: "24.06.23:", desc: "Rebase master to Alpine 3.18, deprecate armhf as per [https://www.linuxserver.io/armhf](https://www.linuxserver.io/armhf)." } + - { date: "26.04.23:", desc: "Rework branches. Swap alpine and ubuntu builds." } + - { date: "29.01.23:", desc: "Rebase to alpine 3.17." } + - { date: "10.01.23:", desc: "Add new var to add `PersistentKeepalive` to server config for select peers to survive server IP changes when domain name is used." } + - { date: "26.10.22:", desc: "Better handle unsupported peer names. Improve logging." } + - { date: "12.10.22:", desc: "Add Alpine branch. Optimize wg and coredns services." } + - { date: "04.10.22:", desc: "Rebase to Jammy. Upgrade to s6v3." } + - { date: "16.05.22:", desc: "Improve NAT handling in server mode when multiple ethernet devices are present." } + - { date: "23.04.22:", desc: "Add pre-shared key support. Automatically added to all new peer confs generated, existing ones are left without to ensure no breaking changes." } + - { date: "10.04.22:", desc: "Rebase to Ubuntu Focal. Add `LOG_CONFS` env var. Remove deprecated `add-peer` command." } + - { date: "28.10.21:", desc: "Add site-to-site vpn support." } - { date: "11.02.21:", desc: "Fix bug related to changing internal subnet and named peer confs not updating." } - { date: "06.10.20:", desc: "Disable CoreDNS in client mode, or if port 53 is already in use in server mode." } - { date: "04.10.20:", desc: "Allow to specify a list of names as PEERS and add ALLOWEDIPS environment variable. Also, add peer name/id to each one of the peer sections in wg0.conf. Important: Existing users need to delete `/config/templates/peer.conf` and restart" } diff --git a/root/app/add-peer b/root/app/add-peer deleted file mode 100755 index ed33bde9..00000000 --- a/root/app/add-peer +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/with-contenv bash - -echo "******* This script has been deprecated and will be removed in a future version. In order to add peers, change the PEERS env var and recreate your container. Existing peers will still use the same private and public keys. *******" - -if [ ! -f /config/wg0.conf ] || [ -z "$PEERS" ]; then - echo "Wireguard is not set up in server mode" - exit 0 -fi - -INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} -INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') -SERVERPORT=${SERVERPORT:-51820} - -if [ -z "$PEERDNS" ] || [ "$PEERDNS" = "auto" ]; then - PEERDNS="${INTERFACE}.1" -fi - -if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - - # If _DAPPNODE_GLOBAL_HOSTNAME is set, use it as SERVERURL - if [ ! -z "$_DAPPNODE_GLOBAL_HOSTNAME" ]; then - echo "**** _DAPPNODE_GLOBAL_HOSTNAME is set, using it as SERVERURL ****" - SERVERURL="$_DAPPNODE_GLOBAL_HOSTNAME" - else - function fetchDappnodeDomain { - for i in {1..10}; do - for domain in "$@"; do - echo "**** Fetching DAppNode domain from $domain..." - SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") - if [ ! -z "$SERVERURL" ]; then - break - fi - sleep 2 - done - done - } - - domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7" "10.20.0.7") - - fetchDappnodeDomain "${domains[@]}" - fi - -fi - -for i in {1..254}; do - if grep -q "AllowedIPs = ${INTERFACE}.$(($i + 1))/32" /config/wg0.conf; then - echo "Peer $i exists" - else - echo "Adding new Peer $i" - mkdir -p /config/peer${i} - if [ ! -f /config/peer${i}/privatekey-peer${i} ]; then - umask 077 - wg genkey | tee /config/peer${i}/privatekey-peer${i} | wg pubkey >/config/peer${i}/publickey-peer${i} - fi - eval "$(printf %s) - cat <<DUDE > /config/peer${i}/peer${i}.conf -$(cat /config/templates/peer.conf) -DUDE" - cat <<DUDE >>/config/wg0.conf -[Peer] -PublicKey = $(cat /config/peer${i}/publickey-peer${i}) -AllowedIPs = ${INTERFACE}.$(($i + 1))/32 - -DUDE - echo "PEER ${i} QR code:" - qrencode -t ansiutf8 </config/peer${i}/peer${i}.conf - qrencode -o /config/peer${i}/peer${i}.png </config/peer${i}/peer${i}.conf - chown -R abc:abc /config/peer${i} - s6-svc -t /var/run/s6/services/wireguard - break - fi -done diff --git a/root/app/show-peer b/root/app/show-peer index a4523f9e..f44b9e58 100755 --- a/root/app/show-peer +++ b/root/app/show-peer @@ -1,6 +1,7 @@ #!/usr/bin/with-contenv bash +# shellcheck shell=bash -if [ ! $# -gt 0 ]; then +if [[ ! $# -gt 0 ]]; then echo "You need to specify which peers to show" exit 0 fi @@ -18,4 +19,4 @@ for i in "$@"; do else echo "PEER ${i} is not active" fi -done \ No newline at end of file +done diff --git a/root/defaults/Corefile b/root/defaults/Corefile index c8e2152f..12da8187 100644 --- a/root/defaults/Corefile +++ b/root/defaults/Corefile @@ -1,4 +1,5 @@ . { loop + health forward . /etc/resolv.conf -} \ No newline at end of file +} diff --git a/root/defaults/peer.conf b/root/defaults/peer.conf index 205a1bdb..d987dba9 100644 --- a/root/defaults/peer.conf +++ b/root/defaults/peer.conf @@ -6,5 +6,6 @@ DNS = ${PEERDNS} [Peer] PublicKey = $(cat /config/server/publickey-server) +PresharedKey = $(cat /config/${PEER_ID}/presharedkey-${PEER_ID}) Endpoint = ${SERVERURL}:${SERVERPORT} -AllowedIPs = ${ALLOWEDIPS} \ No newline at end of file +AllowedIPs = ${ALLOWEDIPS} diff --git a/root/etc/cont-init.d/30-config b/root/etc/cont-init.d/30-config deleted file mode 100644 index 6d7a570a..00000000 --- a/root/etc/cont-init.d/30-config +++ /dev/null @@ -1,326 +0,0 @@ -#!/usr/bin/with-contenv bash - -mkdir -p /config/{templates,coredns} - -echo "Uname info: $(uname -a)" -# check for wireguard module -ip link del dev test 2>/dev/null -if ip link add dev test type wireguard; then - echo "**** It seems the wireguard module is already active. Skipping kernel header install and module compilation. ****" - SKIP_COMPILE="true" - ip link del dev test -else - echo "**** The wireguard module is not active, will attempt kernel header install and module compilation. If you believe that your kernel should have wireguard support already, make sure that it is activated via modprobe! ****" -fi - -# install headers if necessary -if [ "$SKIP_COMPILE" != "true" ] && [ ! -e /lib/modules/$(uname -r)/build ]; then - echo "**** Attempting kernel header install ****" - apt-get update - if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then - apt-get install -y \ - linux-headers-$(uname -r) - elif (uname -r | grep -q 'v7+') || (uname -r | grep -q 'v7l+') || (uname -r | grep -q 'v8+'); then - echo "**** Raspbian kernel naming convention detected, attempting to install raspbian kernel headers ****" - curl -s http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - - echo -e \ - "deb http://archive.raspberrypi.org/debian/ buster main\ndeb-src http://archive.raspberrypi.org/debian/ buster main" \ - >/etc/apt/sources.list.d/raspbian.list - apt-get update - apt-get install -y \ - raspberrypi-kernel-headers - elif uname -v | grep -q 'Ubuntu'; then - echo "**** Ubuntu kernel detected, but likely not Focal. ****" - echo "**** Attempting to install kernel headers from Ubuntu Bionic repo ****" - if uname -m | grep -q 'x86_64'; then - echo -e \ - "deb http://archive.ubuntu.com/ubuntu/ bionic main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ bionic main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ bionic-updates main restricted" \ - >/etc/apt/sources.list.d/xenial-bionic.list - else - echo -e \ - "deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted\n\ndeb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted\ndeb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted" \ - >/etc/apt/sources.list.d/xenial-bionic.list - fi - apt-get update - if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then - apt-get install -y \ - linux-headers-$(uname -r) - else - echo "**** No kernel headers found in the Ubuntu Bionic repo!! Trying Ubuntu Xenial. ****" - sed -i 's/bionic/xenial/g' /etc/apt/sources.list.d/xenial-bionic.list - apt-get update - if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then - apt-get install -y \ - linux-headers-$(uname -r) - else - echo "**** No kernel headers found in the Ubuntu repos!! Will try the headers from host (if mapped), may or may not work ****" - rm -rf /etc/apt/sources.list.d/xenial-bionic.list - fi - fi - elif uname -v | grep -q 'Debian'; then - echo "**** Debian host detected, attempting to install kernel headers from Debian Buster repo ****" - curl -s https://ftp-master.debian.org/keys/archive-key-10.asc | apt-key add - - curl -s https://ftp-master.debian.org/keys/archive-key-10-security.asc | apt-key add - - cat <<DUDE >/etc/apt/sources.list.d/debian.list -deb http://deb.debian.org/debian buster main contrib non-free -deb-src http://deb.debian.org/debian buster main contrib non-free -deb http://deb.debian.org/debian-security/ buster/updates main contrib non-free -deb-src http://deb.debian.org/debian-security/ buster/updates main contrib non-free -deb http://deb.debian.org/debian buster-updates main contrib non-free -deb-src http://deb.debian.org/debian buster-updates main contrib non-free -deb http://deb.debian.org/debian buster-backports main contrib non-free -deb-src http://deb.debian.org/debian buster-backports main contrib non-free -DUDE - apt-get update - if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then - if uname -r | grep -qs "bpo"; then - echo "**** Backported kernel detected ****" - apt-get install -y -t buster-backports \ - linux-headers-$(uname -r) - else - apt-get install -y \ - linux-headers-$(uname -r) - fi - else - echo "**** Attempting to install kernel headers from the Debian Stretch repo ****" - curl -s https://ftp-master.debian.org/keys/archive-key-9.asc | apt-key add - - curl -s https://ftp-master.debian.org/keys/archive-key-9-security.asc | apt-key add - - sed -i 's/buster/stretch/g' /etc/apt/sources.list.d/debian.list - apt-get update - if apt-cache show linux-headers-$(uname -r) 2 &>1 >/dev/null; then - if uname -r | grep -qs "bpo"; then - echo "**** Backported kernel detected ****" - apt-get install -y -t stretch-backports \ - linux-headers-$(uname -r) - else - apt-get install -y \ - linux-headers-$(uname -r) - fi - else - echo "**** No kernel headers found in Debian repos!! Will try the headers from host (if mapped), may or may not work ****" - rm -rf /etc/apt/sources.list.d/debian.list - fi - fi - else - echo "**** No kernel headers found in the Ubuntu or Debian repos!! Will try the headers from host (if mapped), may or may not work ****" - fi -fi - -if [ "$SKIP_COMPILE" != "true" ]; then - if [ -e /lib/modules/$(uname -r)/build ]; then - echo "**** Kernel headers seem to be present, attempting to build the wireguard module. . . ****" - if [ ! -f /lib/modules/$(uname -r)/build/certs/signing_key.pem ]; then - mkdir -p /lib/modules/$(uname -r)/build/certs - cd /lib/modules/$(uname -r)/build/certs - cat <<DUDE >>x509.genkey -[ req ] -default_bits = 4096 -distinguished_name = req_distinguished_name -prompt = no -string_mask = utf8only -x509_extensions = myexts - -[ req_distinguished_name ] -CN = Modules - -[ myexts ] -basicConstraints=critical,CA:FALSE -keyUsage=digitalSignature -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid -DUDE - echo "**** Generating signing key ****" - openssl req -new -nodes -utf8 -sha512 -days 36500 -batch -x509 -config x509.genkey -outform DER -out signing_key.x509 -keyout signing_key.pem - fi - cd /app - for release in "" "v1.0.20200520" "v1.0.20200330" "v0.0.20200105"; do - echo "**** Building the module ****" - if ! [ -z ${release} ]; then - echo "Wireguard release ${release} set, checking out correct version" - cd wireguard-linux-compat - git checkout $release - cd .. - fi - make -C wireguard-linux-compat/src -j$(nproc) && returncode=$? || returncode=$? - if [ $returncode -ne 0 ]; then continue; fi - make -C wireguard-linux-compat/src install && returncode=$? || returncode=$? - if [ $returncode -eq 0 ]; then break; fi - done - echo "**** Let's test our new module. ****" - ip link del dev test 2>/dev/null - if ip link add dev test type wireguard; then - echo "**** The module is active, moving forward with setup. ****" - ip link del dev test - else - echo "**** The module is not active, review the logs. Sleeping now. . . ****" - sleep infinity - fi - else - echo "**** Kernel headers don't seem to be available in Ubuntu, Debian and Raspbian repos, or shared from the host; therefore can't compile the module. Sleeping now. . . ****" - sleep infinity - fi -fi - -# prepare symlinks -rm -rf /etc/wireguard -mkdir -p /etc/wireguard -ln -s /config/wg0.conf /etc/wireguard/wg0.conf -# prepare templates -[[ ! -f /config/templates/server.conf ]] && - cp /defaults/server.conf /config/templates/server.conf -[[ ! -f /config/templates/peer.conf ]] && - cp /defaults/peer.conf /config/templates/peer.conf - -generate_confs() { - mkdir -p /config/server - if [ ! -f /config/server/privatekey-server ]; then - umask 077 - wg genkey | tee /config/server/privatekey-server | wg pubkey >/config/server/publickey-server - fi - eval "$(printf %s) - cat <<DUDE > /config/wg0.conf -$(cat /config/templates/server.conf) - -DUDE" - for i in ${PEERS_ARRAY[@]}; do - if [[ "${i}" =~ ^[0-9]+$ ]]; then - PEER_ID="peer${i}" - else - PEER_ID="peer_${i//[^[:alnum:]_-]/}" - fi - mkdir -p /config/${PEER_ID} - if [ ! -f "/config/${PEER_ID}/privatekey-${PEER_ID}" ]; then - umask 077 - wg genkey | tee /config/${PEER_ID}/privatekey-${PEER_ID} | wg pubkey >/config/${PEER_ID}/publickey-${PEER_ID} - fi - if [ -f "/config/${PEER_ID}/${PEER_ID}.conf" ]; then - CLIENT_IP=$(cat /config/${PEER_ID}/${PEER_ID}.conf | grep "Address" | awk '{print $NF}') - if [ -n "${ORIG_INTERFACE}" ] && [ "${INTERFACE}" != "${ORIG_INTERFACE}" ]; then - CLIENT_IP=$(echo "${CLIENT_IP}" | sed "s|${ORIG_INTERFACE}|${INTERFACE}|") - fi - else - for idx in {2..254}; do - PROPOSED_IP="${INTERFACE}.${idx}" - if ! grep -q -R "${PROPOSED_IP}" /config/peer*/*.conf && ([ -z "${ORIG_INTERFACE}" ] || ! grep -q -R "${ORIG_INTERFACE}.${idx}" /config/peer*/*.conf); then - CLIENT_IP="${PROPOSED_IP}" - break - fi - done - fi - eval "$(printf %s) - cat <<DUDE > /config/${PEER_ID}/${PEER_ID}.conf -$(cat /config/templates/peer.conf) -DUDE" - cat <<DUDE >>/config/wg0.conf -[Peer] -# ${PEER_ID} -PublicKey = $(cat /config/${PEER_ID}/publickey-${PEER_ID}) -AllowedIPs = ${CLIENT_IP}/32 - -DUDE - echo "PEER ${i} QR code:" - qrencode -t ansiutf8 </config/${PEER_ID}/${PEER_ID}.conf - qrencode -o /config/${PEER_ID}/${PEER_ID}.png </config/${PEER_ID}/${PEER_ID}.conf - done -} - -save_vars() { - cat <<DUDE >/config/.donoteditthisfile -ORIG_SERVERURL="$SERVERURL" -ORIG_SERVERPORT="$SERVERPORT" -ORIG_PEERDNS="$PEERDNS" -ORIG_PEERS="$PEERS" -ORIG_INTERFACE="$INTERFACE" -ORIG_ALLOWEDIPS="$ALLOWEDIPS" -DUDE -} - -if [ -n "$PEERS" ]; then - echo "**** Server mode is selected ****" - if [[ "$PEERS" =~ ^[0-9]+$ ]] && ! [[ "$PEERS" =~ *,* ]]; then - PEERS_ARRAY=($(seq 1 $PEERS)) - else - PEERS_ARRAY=($(echo "$PEERS" | tr ',' ' ')) - fi - PEERS_COUNT=$(echo "${#PEERS_ARRAY[@]}") - if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then - - # If _DAPPNODE_GLOBAL_HOSTNAME is set, use it as SERVERURL - if [ ! -z "$_DAPPNODE_GLOBAL_HOSTNAME" ]; then - echo "**** _DAPPNODE_GLOBAL_HOSTNAME is set, using it as SERVERURL ****" - SERVERURL="$_DAPPNODE_GLOBAL_HOSTNAME" - else - - function fetchDappnodeDomain { - for i in {1..30}; do - for domain in "$@"; do - echo "**** Fetching DAppNode domain from $domain..." - SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") - if [ ! -z "$SERVERURL" ]; then - break 2 - fi - sleep 2 - done - done - } - - domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7" "10.20.0.7") - - fetchDappnodeDomain "${domains[@]}" - fi - - if [ -z "$SERVERURL" ]; then - echo "**** SERVERURL var is either not set or is set to \"auto\", setting external IP to auto detected value of $SERVERURL ****" - else - echo "**** SERVERURL var is set to $SERVERURL ****" - fi - else - echo "**** External server address is set to $SERVERURL ****" - fi - - SERVERPORT=${SERVERPORT:-51820} - echo "**** External server port is set to ${SERVERPORT}. Make sure that port is properly forwarded to port 51820 inside this container ****" - INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} - echo "**** Internal subnet is set to $INTERNAL_SUBNET ****" - INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') - ALLOWEDIPS=${ALLOWEDIPS:-0.0.0.0/0, ::/0} - echo "**** AllowedIPs for peers $ALLOWEDIPS ****" - if [ -z "$PEERDNS" ] || [ "$PEERDNS" = "auto" ]; then - PEERDNS="${INTERFACE}.1" - echo "**** PEERDNS var is either not set or is set to \"auto\", setting peer DNS to ${INTERFACE}.1 to use wireguard docker host's DNS. ****" - else - echo "**** Peer DNS servers will be set to $PEERDNS ****" - fi - if [ ! -f /config/wg0.conf ]; then - echo "**** No wg0.conf found (maybe an initial install), generating 1 server and ${PEERS} peer/client confs ****" - generate_confs - save_vars - else - echo "**** Server mode is selected ****" - [[ -f /config/.donoteditthisfile ]] && - . /config/.donoteditthisfile - if [ "$SERVERURL" != "$ORIG_SERVERURL" ] || [ "$SERVERPORT" != "$ORIG_SERVERPORT" ] || [ "$PEERDNS" != "$ORIG_PEERDNS" ] || [ "$PEERS" != "$ORIG_PEERS" ] || [ "$INTERFACE" != "$ORIG_INTERFACE" ] || [ "$ALLOWEDIPS" != "$ORIG_ALLOWEDIPS" ]; then - echo "**** Server related environment variables changed, regenerating 1 server and ${PEERS} peer/client confs ****" - generate_confs - save_vars - else - echo "**** No changes to parameters. Existing configs are used. ****" - fi - fi -else - echo "**** Client mode selected. ****" - if [ ! -f /config/wg0.conf ]; then - echo "**** No client conf found. Provide your own client conf as \"/config/wg0.conf\" and restart the container. ****" - sleep infinity - fi - echo "**** Disabling CoreDNS ****" - rm -rf /etc/services.d/coredns -fi - -# set up CoreDNS -[[ ! -f /config/coredns/Corefile ]] && - cp /defaults/Corefile /config/coredns/Corefile - -# permissions -chown -R abc:abc \ - /config diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-end/dependencies.d/init-wireguard-confs b/root/etc/s6-overlay/s6-rc.d/init-config-end/dependencies.d/init-wireguard-confs new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/dependencies.d/init-wireguard-module b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/dependencies.d/init-wireguard-module new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/run b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/run new file mode 100755 index 00000000..48bdd938 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/run @@ -0,0 +1,221 @@ +#!/usr/bin/with-contenv bash +# shellcheck shell=bash +# shellcheck disable=SC2016,SC1091,SC2183 + +# prepare symlinks +rm -rf /etc/wireguard +mkdir -p /etc/wireguard +ln -s /config/wg0.conf /etc/wireguard/wg0.conf +# prepare templates +if [[ ! -f /config/templates/server.conf ]]; then + cp /defaults/server.conf /config/templates/server.conf +fi +if [[ ! -f /config/templates/peer.conf ]]; then + cp /defaults/peer.conf /config/templates/peer.conf +fi +# add preshared key to user templates (backwards compatibility) +if ! grep -q 'PresharedKey' /config/templates/peer.conf; then + sed -i 's|^Endpoint|PresharedKey = \$\(cat /config/\${PEER_ID}/presharedkey-\${PEER_ID}\)\nEndpoint|' /config/templates/peer.conf +fi + +generate_confs () { + mkdir -p /config/server + if [[ ! -f /config/server/privatekey-server ]]; then + umask 077 + wg genkey | tee /config/server/privatekey-server | wg pubkey > /config/server/publickey-server + fi + eval "$(printf %s) + cat <<DUDE > /config/wg0.conf +$(cat /config/templates/server.conf) + +DUDE" + for i in "${PEERS_ARRAY[@]}"; do + if [[ ! "${i}" =~ ^[[:alnum:]]+$ ]]; then + echo "**** Peer ${i} contains non-alphanumeric characters and thus will be skipped. No config for peer ${i} will be generated. ****" + else + if [[ "${i}" =~ ^[0-9]+$ ]]; then + PEER_ID="peer${i}" + else + PEER_ID="peer_${i}" + fi + mkdir -p "/config/${PEER_ID}" + if [[ ! -f "/config/${PEER_ID}/privatekey-${PEER_ID}" ]]; then + umask 077 + wg genkey | tee "/config/${PEER_ID}/privatekey-${PEER_ID}" | wg pubkey > "/config/${PEER_ID}/publickey-${PEER_ID}" + wg genpsk > "/config/${PEER_ID}/presharedkey-${PEER_ID}" + fi + if [[ -f "/config/${PEER_ID}/${PEER_ID}.conf" ]]; then + CLIENT_IP=$(grep "Address" "/config/${PEER_ID}/${PEER_ID}.conf" | awk '{print $NF}') + if [[ -n "${ORIG_INTERFACE}" ]] && [[ "${INTERFACE}" != "${ORIG_INTERFACE}" ]]; then + CLIENT_IP="${CLIENT_IP//${ORIG_INTERFACE}/${INTERFACE}}" + fi + else + for idx in {2..254}; do + PROPOSED_IP="${INTERFACE}.${idx}" + if ! grep -q -R "${PROPOSED_IP}" /config/peer*/*.conf 2>/dev/null && ([[ -z "${ORIG_INTERFACE}" ]] || ! grep -q -R "${ORIG_INTERFACE}.${idx}" /config/peer*/*.conf 2>/dev/null); then + CLIENT_IP="${PROPOSED_IP}" + break + fi + done + fi + if [[ -f "/config/${PEER_ID}/presharedkey-${PEER_ID}" ]]; then + # create peer conf with presharedkey + eval "$(printf %s) + cat <<DUDE > /config/${PEER_ID}/${PEER_ID}.conf +$(cat /config/templates/peer.conf) +DUDE" + # add peer info to server conf with presharedkey + cat <<DUDE >> /config/wg0.conf +[Peer] +# ${PEER_ID} +PublicKey = $(cat "/config/${PEER_ID}/publickey-${PEER_ID}") +PresharedKey = $(cat "/config/${PEER_ID}/presharedkey-${PEER_ID}") +DUDE + else + echo "**** Existing keys with no preshared key found for ${PEER_ID}, creating confs without preshared key for backwards compatibility ****" + # create peer conf without presharedkey + eval "$(printf %s) + cat <<DUDE > /config/${PEER_ID}/${PEER_ID}.conf +$(sed '/PresharedKey/d' "/config/templates/peer.conf") +DUDE" + # add peer info to server conf without presharedkey + cat <<DUDE >> /config/wg0.conf +[Peer] +# ${PEER_ID} +PublicKey = $(cat "/config/${PEER_ID}/publickey-${PEER_ID}") +DUDE + fi + SERVER_ALLOWEDIPS=SERVER_ALLOWEDIPS_PEER_${i} + # add peer's allowedips to server conf + if [[ -n "${!SERVER_ALLOWEDIPS}" ]]; then + echo "Adding ${!SERVER_ALLOWEDIPS} to wg0.conf's AllowedIPs for peer ${i}" + cat <<DUDE >> /config/wg0.conf +AllowedIPs = ${CLIENT_IP}/32,${!SERVER_ALLOWEDIPS} +DUDE + else + cat <<DUDE >> /config/wg0.conf +AllowedIPs = ${CLIENT_IP}/32 +DUDE + fi + # add PersistentKeepalive if the peer is specified + if [[ -n "${PERSISTENTKEEPALIVE_PEERS_ARRAY}" ]] && ([[ "${PERSISTENTKEEPALIVE_PEERS_ARRAY[0]}" = "all" ]] || printf '%s\0' "${PERSISTENTKEEPALIVE_PEERS_ARRAY[@]}" | grep -Fxqz -- "${i}"); then + cat <<DUDE >> /config/wg0.conf +PersistentKeepalive = 25 + +DUDE + else + cat <<DUDE >> /config/wg0.conf + +DUDE + fi + if [[ -z "${LOG_CONFS}" ]] || [[ "${LOG_CONFS}" = "true" ]]; then + echo "PEER ${i} QR code (conf file is saved under /config/${PEER_ID}):" + qrencode -t ansiutf8 < "/config/${PEER_ID}/${PEER_ID}.conf" + else + echo "PEER ${i} conf and QR code png saved in /config/${PEER_ID}" + fi + qrencode -o "/config/${PEER_ID}/${PEER_ID}.png" < "/config/${PEER_ID}/${PEER_ID}.conf" + fi + done +} + +save_vars () { + cat <<DUDE > /config/.donoteditthisfile +ORIG_SERVERURL="$SERVERURL" +ORIG_SERVERPORT="$SERVERPORT" +ORIG_PEERDNS="$PEERDNS" +ORIG_PEERS="$PEERS" +ORIG_INTERFACE="$INTERFACE" +ORIG_ALLOWEDIPS="$ALLOWEDIPS" +ORIG_PERSISTENTKEEPALIVE_PEERS="$PERSISTENTKEEPALIVE_PEERS" +DUDE +} + +if [[ -n "$PEERS" ]]; then + echo "**** Server mode is selected ****" + if [[ "$PEERS" =~ ^[0-9]+$ ]] && ! [[ "$PEERS" = *,* ]]; then + mapfile -t PEERS_ARRAY < <(seq 1 "${PEERS}") + else + mapfile -t PEERS_ARRAY < <(echo "${PEERS}" | tr ',' '\n') + fi + if [[ -n "${PERSISTENTKEEPALIVE_PEERS}" ]]; then + echo "**** PersistentKeepalive will be set for: ${PERSISTENTKEEPALIVE_PEERS/,/ } ****" + mapfile -t PERSISTENTKEEPALIVE_PEERS_ARRAY < <(echo "${PERSISTENTKEEPALIVE_PEERS}" | tr ',' '\n') + fi + + if [ -z "$SERVERURL" ] || [ "$SERVERURL" = "auto" ]; then + + # If _DAPPNODE_GLOBAL_HOSTNAME is set, use it as SERVERURL + if [ ! -z "$_DAPPNODE_GLOBAL_HOSTNAME" ]; then + echo "**** _DAPPNODE_GLOBAL_HOSTNAME is set, using it as SERVERURL ****" + SERVERURL="$_DAPPNODE_GLOBAL_HOSTNAME" + else + function fetchDappnodeDomain { + for i in {1..10}; do + for domain in "$@"; do + echo "**** Fetching DAppNode domain from $domain..." + SERVERURL=$(curl -s "$domain/global-envs/HOSTNAME") + if [ ! -z "$SERVERURL" ]; then + break + fi + sleep 2 + done + done + } + + domains=("my.dappnode" "dappmanager.dappnode" "172.33.1.7" "10.20.0.7") + + fetchDappnodeDomain "${domains[@]}" + fi + + else + echo "**** External server address is set to $SERVERURL ****" + fi + SERVERPORT=${SERVERPORT:-51820} + echo "**** External server port is set to ${SERVERPORT}. Make sure that port is properly forwarded to port 51820 inside this container ****" + INTERNAL_SUBNET=${INTERNAL_SUBNET:-10.13.13.0} + echo "**** Internal subnet is set to $INTERNAL_SUBNET ****" + INTERFACE=$(echo "$INTERNAL_SUBNET" | awk 'BEGIN{FS=OFS="."} NF--') + ALLOWEDIPS=${ALLOWEDIPS:-0.0.0.0/0, ::/0} + echo "**** AllowedIPs for peers $ALLOWEDIPS ****" + if [[ -z "$PEERDNS" ]] || [[ "$PEERDNS" = "auto" ]]; then + PEERDNS="${INTERFACE}.1" + echo "**** PEERDNS var is either not set or is set to \"auto\", setting peer DNS to ${INTERFACE}.1 to use wireguard docker host's DNS. ****" + else + echo "**** Peer DNS servers will be set to $PEERDNS ****" + fi + if [[ ! -f /config/wg0.conf ]]; then + echo "**** No wg0.conf found (maybe an initial install), generating 1 server and ${PEERS} peer/client confs ****" + generate_confs + save_vars + else + echo "**** Server mode is selected ****" + if [[ -f /config/.donoteditthisfile ]]; then + . /config/.donoteditthisfile + fi + if [[ "$SERVERURL" != "$ORIG_SERVERURL" ]] || [[ "$SERVERPORT" != "$ORIG_SERVERPORT" ]] || [[ "$PEERDNS" != "$ORIG_PEERDNS" ]] || [[ "$PEERS" != "$ORIG_PEERS" ]] || [[ "$INTERFACE" != "$ORIG_INTERFACE" ]] || [[ "$ALLOWEDIPS" != "$ORIG_ALLOWEDIPS" ]] || [[ "$PERSISTENTKEEPALIVE_PEERS" != "$ORIG_PERSISTENTKEEPALIVE_PEERS" ]]; then + echo "**** Server related environment variables changed, regenerating 1 server and ${PEERS} peer/client confs ****" + generate_confs + save_vars + else + echo "**** No changes to parameters. Existing configs are used. ****" + fi + fi +else + echo "**** Client mode selected. ****" + if [[ ! -f /config/wg0.conf ]]; then + echo "**** No client conf found. Provide your own client conf as \"/config/wg0.conf\" and restart the container. ****" + sleep infinity + fi + USE_COREDNS="${USE_COREDNS,,}" + printf %s "${USE_COREDNS:-false}" > /run/s6/container_environment/USE_COREDNS +fi + +# set up CoreDNS +if [[ ! -f /config/coredns/Corefile ]]; then + cp /defaults/Corefile /config/coredns/Corefile +fi + +# permissions +lsiown -R abc:abc \ + /config diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/type b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/type new file mode 100644 index 00000000..bdd22a18 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/type @@ -0,0 +1 @@ +oneshot diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/up b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/up new file mode 100644 index 00000000..892cce9e --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-wireguard-confs/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-wireguard-confs/run diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/dependencies.d/init-config b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/dependencies.d/init-config new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/run b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/run new file mode 100755 index 00000000..462ae87a --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/run @@ -0,0 +1,18 @@ +#!/usr/bin/with-contenv bash + +mkdir -p /config/{templates,coredns} + +echo "Uname info: $(uname -a)" +# check for wireguard module +ip link del dev test 2>/dev/null +if ip link add dev test type wireguard; then + echo "**** It seems the wireguard module is already active. Skipping kernel header install and module compilation. ****" + ip link del dev test + if capsh --current | grep "Current:" | grep -q "cap_sys_module"; then + echo "**** As the wireguard module is already active you can remove the SYS_MODULE capability from your container run/compose. ****" + fi +else + echo "**** The wireguard module is not active. If you believe that your kernel should have wireguard support already, make sure that it is activated via modprobe! ****" + echo "**** If you have an old kernel without wireguard support built-in, you can try using the "legacy" tag for this image to compile the modules from scratch. ****" + sleep infinity +fi diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/type b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/type new file mode 100644 index 00000000..bdd22a18 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/type @@ -0,0 +1 @@ +oneshot diff --git a/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/up b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/up new file mode 100644 index 00000000..b197ae8e --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-wireguard-module/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-wireguard-module/run diff --git a/root/etc/s6-overlay/s6-rc.d/svc-coredns/dependencies.d/init-services b/root/etc/s6-overlay/s6-rc.d/svc-coredns/dependencies.d/init-services new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/svc-coredns/notification-fd b/root/etc/s6-overlay/s6-rc.d/svc-coredns/notification-fd new file mode 100644 index 00000000..00750edc --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-coredns/notification-fd @@ -0,0 +1 @@ +3 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-coredns/run b/root/etc/s6-overlay/s6-rc.d/svc-coredns/run new file mode 100755 index 00000000..f9a478c3 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-coredns/run @@ -0,0 +1,23 @@ +#!/usr/bin/with-contenv bash +# shellcheck shell=bash + +if netstat -apn | grep -q ":53 " && [[ -z "${USE_COREDNS}" ]]; then + USE_COREDNS="false" +fi + +if [[ ${USE_COREDNS} == "false" ]]; then + s6-notifyoncheck -d -n 300 -w 1000 -c "echo **** Disabling CoreDNS ****" \ + sleep infinity +else + if grep -q "health" /config/coredns/Corefile; then + exec \ + s6-notifyoncheck -d -n 300 -w 1000 -c "redirfd -w 1 /dev/null curl -s http://localhost:8080/health" \ + cd /config/coredns \ + /usr/bin/coredns -dns.port=53 + else + exec \ + s6-notifyoncheck -d -n 300 -w 1000 -c "nc -zu localhost 53" \ + cd /config/coredns \ + /usr/bin/coredns -dns.port=53 + fi +fi diff --git a/root/etc/s6-overlay/s6-rc.d/svc-coredns/type b/root/etc/s6-overlay/s6-rc.d/svc-coredns/type new file mode 100644 index 00000000..5883cff0 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-coredns/type @@ -0,0 +1 @@ +longrun diff --git a/root/etc/s6-overlay/s6-rc.d/svc-wireguard/dependencies.d/svc-coredns b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/dependencies.d/svc-coredns new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/svc-wireguard/down b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/down new file mode 100644 index 00000000..5ef932fc --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/down @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/svc-wireguard/finish diff --git a/root/etc/s6-overlay/s6-rc.d/svc-wireguard/finish b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/finish new file mode 100755 index 00000000..9a5d2135 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/finish @@ -0,0 +1,4 @@ +#!/usr/bin/with-contenv bash +# shellcheck shell=bash + +wg-quick down wg0 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-wireguard/run b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/run new file mode 100755 index 00000000..47ce7565 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/run @@ -0,0 +1,4 @@ +#!/usr/bin/with-contenv bash +# shellcheck shell=bash + +wg-quick up wg0 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-wireguard/type b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/type new file mode 100644 index 00000000..bdd22a18 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/type @@ -0,0 +1 @@ +oneshot diff --git a/root/etc/s6-overlay/s6-rc.d/svc-wireguard/up b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/up new file mode 100644 index 00000000..47b67d6b --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-wireguard/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/svc-wireguard/run diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-wireguard-confs b/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-wireguard-confs new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-wireguard-module b/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-wireguard-module new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-coredns b/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-coredns new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-wireguard b/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-wireguard new file mode 100644 index 00000000..e69de29b diff --git a/root/etc/services.d/coredns/run b/root/etc/services.d/coredns/run deleted file mode 100644 index 5448654b..00000000 --- a/root/etc/services.d/coredns/run +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/with-contenv bash - -cd /config/coredns - -if netstat -apn | grep -q ":53 "; then - echo "Another service is using port 53, disabling CoreDNS" - sleep infinity -else - exec \ - /app/coredns -dns.port=53 -fi \ No newline at end of file diff --git a/root/etc/services.d/wireguard/run b/root/etc/services.d/wireguard/run deleted file mode 100644 index 9ef15b46..00000000 --- a/root/etc/services.d/wireguard/run +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/with-contenv bash - -_term() { - echo "Caught SIGTERM signal!" - wg-quick down wg0 -} - -trap _term SIGTERM - -wg-quick up wg0 - -sleep infinity & - -wait From e98529a933de87297a7428eb81d4da51b27caf8f Mon Sep 17 00:00:00 2001 From: pablomendezroyo <mendez4a@gmail.com> Date: Thu, 26 Feb 2026 10:50:35 +0100 Subject: [PATCH 57/57] Add localhost configuration support and related tests - Implement setLocalhostConfig function to modify config for localhost usage. - Update getWireguardCredentials to handle --localhost flag. - Add tests for setLocalhostConfig to ensure correct functionality. --- api/src/createLocalConfigFile.ts | 8 ++-- .../executables/getWireguardCredentials.ts | 12 +++-- api/src/setLocalhostConfig.ts | 9 ++++ api/test/createLocalConfigFile.test.ts | 4 +- api/test/setLocalhostConfig.test.ts | 44 +++++++++++++++++++ 5 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 api/src/setLocalhostConfig.ts create mode 100644 api/test/setLocalhostConfig.test.ts diff --git a/api/src/createLocalConfigFile.ts b/api/src/createLocalConfigFile.ts index 91247048..9fcf92e5 100644 --- a/api/src/createLocalConfigFile.ts +++ b/api/src/createLocalConfigFile.ts @@ -43,7 +43,7 @@ async function getLocalIpWithRetries(retries: number): Promise<string> { async function getLocalIp(): Promise<string> { const dappmanagerHostnames = params.DAPPMANAGER_HOSTNAMES; const getLocalIpUrls = dappmanagerHostnames.map( - (hostname) => `http://${hostname}${params.GET_INTERNAL_IP_ENDPOINT}` + (hostname) => `http://${hostname}${params.GET_INTERNAL_IP_ENDPOINT}`, ); let errorMessages: string[] = []; @@ -57,7 +57,7 @@ async function getLocalIp(): Promise<string> { return localIp; } catch (e) { errorMessages.push( - `Local IP could not be fetched from ${url}: ${e.message}` + `Local IP could not be fetched from ${url}: ${e.message}`, ); } } @@ -66,12 +66,12 @@ async function getLocalIp(): Promise<string> { export function setLocalEndpoint( configFile: string, - localEndpoint: string + localEndpoint: string, ): string { return configFile .split("\n") .map((row) => - row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row + row.startsWith("Endpoint =") ? `Endpoint = ${localEndpoint}` : row, ) .join("\n"); } diff --git a/api/src/executables/getWireguardCredentials.ts b/api/src/executables/getWireguardCredentials.ts index eb5cd472..31b8229c 100644 --- a/api/src/executables/getWireguardCredentials.ts +++ b/api/src/executables/getWireguardCredentials.ts @@ -11,6 +11,7 @@ import { createLocalConfigFile, getRemoteConfigFilePath, } from "../createLocalConfigFile"; +import { setLocalhostConfig } from "../setLocalhostConfig"; import fs from "fs"; (async function (): Promise<void> { @@ -23,20 +24,25 @@ import fs from "fs"; const isQr = process.argv.includes("--qr"); const isLocal = process.argv.includes("--local"); + const isLocalhost = process.argv.includes("--localhost"); const configName = isLocal ? "local" : "remote"; const configFormat = isQr ? "qr" : "text"; console.log( - `Preparing ${configName} ${configFormat} Wireguard credentials; use CTRL + C to stop` + `Preparing ${configName} ${configFormat} Wireguard credentials; use CTRL + C to stop`, ); - const config = isLocal + const baseConfig = isLocal ? await createLocalConfigFile(params.MASTER_ADMIN) : fs.readFileSync( getRemoteConfigFilePath(params.MASTER_ADMIN, "conf"), - "utf-8" + "utf-8", ); + // Mostly required to connect from within the same machine, + // especially when DAppNode is installed on macOS. + const config = isLocalhost ? setLocalhostConfig(baseConfig) : baseConfig; + const str = isQr ? // If rendering the QR fails, show error and the raw remoteTextCreds await renderQrCode(config).catch((e) => { diff --git a/api/src/setLocalhostConfig.ts b/api/src/setLocalhostConfig.ts new file mode 100644 index 00000000..a933add9 --- /dev/null +++ b/api/src/setLocalhostConfig.ts @@ -0,0 +1,9 @@ +export function setLocalhostConfig(configFile: string): string { + return configFile + .split("\n") + .filter((row) => !row.includes("ListenPort")) + .map((row) => + row.match(/^Endpoint\s*=/) ? "Endpoint = localhost:51820" : row, + ) + .join("\n"); +} diff --git a/api/test/createLocalConfigFile.test.ts b/api/test/createLocalConfigFile.test.ts index 82ca376e..fc7da7ce 100644 --- a/api/test/createLocalConfigFile.test.ts +++ b/api/test/createLocalConfigFile.test.ts @@ -28,6 +28,8 @@ AllowedIPs = 0.0.0.0/0`; const localEndpoint = `192.168.1.45:51820`; - expect(setLocalEndpoint(remoteConfig, localEndpoint)).to.deep.equal(expextedLocalConfig); + expect(setLocalEndpoint(remoteConfig, localEndpoint)).to.deep.equal( + expextedLocalConfig, + ); }); }); diff --git a/api/test/setLocalhostConfig.test.ts b/api/test/setLocalhostConfig.test.ts new file mode 100644 index 00000000..0f65acfe --- /dev/null +++ b/api/test/setLocalhostConfig.test.ts @@ -0,0 +1,44 @@ +import "mocha"; +import { expect } from "chai"; +import { setLocalhostConfig } from "../src/setLocalhostConfig"; + +describe("setLocalhostConfig", function () { + it("removes ListenPort and sets localhost endpoint", function () { + const remoteConfig = `[Interface] +Address = AX032NVGI2RIB4 +PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= +ListenPort = 51820 +DNS = 172.33.1.2 + +[Peer] +PublicKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= +Endpoint = ff0239facf453517.dyndns.dappnode.io:51820 +AllowedIPs = 0.0.0.0/0`; + + const expectedLocalhostConfig = `[Interface] +Address = AX032NVGI2RIB4 +PrivateKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw= +DNS = 172.33.1.2 + +[Peer] +PublicKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE= +Endpoint = localhost:51820 +AllowedIPs = 0.0.0.0/0`; + + expect(setLocalhostConfig(remoteConfig)).to.deep.equal( + expectedLocalhostConfig, + ); + }); + + it("replaces endpoint when spacing around equal sign varies", function () { + const remoteConfig = `[Peer] +Endpoint = ff0239facf453517.dyndns.dappnode.io:51820`; + + const expectedLocalhostConfig = `[Peer] +Endpoint = localhost:51820`; + + expect(setLocalhostConfig(remoteConfig)).to.deep.equal( + expectedLocalhostConfig, + ); + }); +});