Simplify process by using bash.

This commit is contained in:
Kevin Baensch 2022-11-04 13:01:36 +01:00
parent b852746352
commit 4679608188
15 changed files with 57 additions and 1612 deletions

4
.gitignore vendored
View file

@ -1,4 +0,0 @@
dist/
node_modules/
.log/
Config/hosts*

View file

@ -1,26 +0,0 @@
{
"admin": {
"disabled": false,
"listen": "",
"enforce_origin": false,
"origins": [""],
"config": {
"persist": false,
"load": {•••}
},
"identity": {
"identifiers": [""],
"issuers": [{•••}]
},
"remote": {
"listen": "",
"access_control": [{
"public_keys": [""],
"permissions": [{
"paths": [""],
"methods": [""]
}]
}]
}
}
}

26
docker-compose.yml Normal file
View file

@ -0,0 +1,26 @@
version: "3.4"
services:
hostman:
image: apteno/alpine-jq
command: ["./hostman.sh", "&", "wait", "$!" ]
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /etc/hosts:/tmp/hosts:rw
- ./hostman.sh:/hostman.sh
networks:
- reverseproxy
nginx-proxy:
image: jwilder/nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- reverseproxy
networks:
reverseproxy:
name: reverseproxy
external: false

31
hostman.sh Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env sh
# Configurable Variables
DOCKER_SOCK_PATH="/tmp/docker.sock"
HOST_CONF_PATH="/tmp/hosts"
NETWORK_NAME="reverseproxy"
query_docker () {
echo $(curl --unix-socket $DOCKER_SOCK_PATH --silent -g http://v1.41/$1/json$2)
}
while true
do
PROXY_HOST_CONF=""
CONTAINER_LIST=$(query_docker "containers" "?filters={%22network%22:[%22${NETWORK_NAME}%22],%22status%22:[%22running%22]}" | jq -cr '.[].Id')
for id in $CONTAINER_LIST
do
# Query individual container to access Env variables
# Filter Env for HOSTNAME, remove list parenthesis and split/only keep values
HOST_NAMES=$(query_docker "containers/${id}" | jq -cr '.Config.Env[] | select(contains("VIRTUAL_HOST=")) | split("=")[1]')
for hostname in $HOST_NAMES
do
PROXY_HOST_CONF="$PROXY_HOST_CONF\n127.0.0.1 $hostname # Added by hostman"
done
done
FILTERED_HOSTS=$(grep -ve "# Added by hostman$" $HOST_CONF_PATH)
echo -e "$FILTERED_HOSTS$PROXY_HOST_CONF" > $HOST_CONF_PATH
sleep 10
done

923
package-lock.json generated
View file

@ -1,923 +0,0 @@
{
"name": "reverseproxy",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "reverseproxy",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"daemon": "^1.1.0",
"node-docker-api": "^1.1.22"
},
"devDependencies": {
"@types/node": "^18.8.4",
"typescript": "^4.8.3",
"typescript-language-server": "^1.2.0"
}
},
"node_modules/@types/node": {
"version": "18.8.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.4.tgz",
"integrity": "sha512-WdlVphvfR/GJCLEMbNA8lJ0lhFNBj4SW3O+O5/cEGw9oYrv0al9zTwuQsq+myDUXgNx2jgBynoVgZ2MMJ6pbow==",
"dev": true
},
"node_modules/commander": {
"version": "9.4.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
"integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==",
"dev": true,
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/crypto-random-string": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz",
"integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==",
"dev": true,
"dependencies": {
"type-fest": "^1.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/crypto-random-string/node_modules/type-fest": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/daemon": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/daemon/-/daemon-1.1.0.tgz",
"integrity": "sha512-1vX9YVcP21gt12nSD3SQRC/uPU7fyA6M8qyClTBIFuiRWoylFn57PwXhjBAqRl085bZAje7sILhZU48qcS9SWw==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/docker-modem": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-0.3.7.tgz",
"integrity": "sha512-4Xn4ZVtc/2DEFtxY04lOVeF7yvxwXGVo0sN8FKRBnLhBcwQ78Hb56j+Z5yAXXUhoweVhzGeBeGWahS+af0/mcg==",
"dependencies": {
"debug": "^2.6.0",
"JSONStream": "0.10.0",
"readable-stream": "~1.0.26-4",
"split-ca": "^1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/find-up": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
"integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
"dev": true,
"dependencies": {
"locate-path": "^7.1.0",
"path-exists": "^5.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/jsonparse": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz",
"integrity": "sha512-fw7Q/8gFR8iSekUi9I+HqWIap6mywuoe7hQIg3buTVjuZgALKj4HAmm0X6f+TaL4c9NJbvyFQdaI2ppr5p6dnQ==",
"engines": [
"node >= 0.2.0"
]
},
"node_modules/JSONStream": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz",
"integrity": "sha512-8XbSFFd43EG+1thjLNFIzCBlwXti0yKa7L+ak/f0T/pkC+31b7G41DXL/JzYpAoYWZ2eCPiu4IIqzijM8N0a/w==",
"dependencies": {
"jsonparse": "0.0.5",
"through": ">=2.2.7 <3"
},
"bin": {
"JSONStream": "index.js"
},
"engines": {
"node": "*"
}
},
"node_modules/locate-path": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.1.1.tgz",
"integrity": "sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg==",
"dev": true,
"dependencies": {
"p-locate": "^6.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/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,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/node-docker-api": {
"version": "1.1.22",
"resolved": "https://registry.npmjs.org/node-docker-api/-/node-docker-api-1.1.22.tgz",
"integrity": "sha512-8xfOiuLDJQw+l58i66lUNQhRhS5fAExqQbLolmyqMucrsDON7k7eLMIHphcBwwB7utwCHCQkcp73gSAmzSiAiw==",
"dependencies": {
"docker-modem": "^0.3.1",
"memorystream": "^0.3.1"
}
},
"node_modules/p-debounce": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-4.0.0.tgz",
"integrity": "sha512-4Ispi9I9qYGO4lueiLDhe4q4iK5ERK8reLsuzH6BPaXn53EGaua8H66PXIFGrW897hwjXp+pVLrm/DLxN0RF0A==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/p-limit": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
"integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
"dev": true,
"dependencies": {
"yocto-queue": "^1.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
"integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
"dev": true,
"dependencies": {
"p-limit": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-exists": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
"integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/pkg-up": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-4.0.0.tgz",
"integrity": "sha512-N4zdA4sfOe6yCv+ulPCmpnIBQ5I60xfhDr1otdBBhKte9QtEf3bhfrfkW7dTb+IQ0iEx4ZDzas0kc1o5rdWpYg==",
"dev": true,
"dependencies": {
"find-up": "^6.2.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/split-ca": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz",
"integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ=="
},
"node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
"node_modules/temp-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
"integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/tempy": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz",
"integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==",
"dev": true,
"dependencies": {
"is-stream": "^3.0.0",
"temp-dir": "^2.0.0",
"type-fest": "^2.12.2",
"unique-string": "^3.0.0"
},
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"node_modules/type-fest": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
"dev": true,
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typescript": {
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
"integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/typescript-language-server": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/typescript-language-server/-/typescript-language-server-1.2.0.tgz",
"integrity": "sha512-Ahxko4dKgOY/pGTMdzeVw/NTIZC4z33OqEs7xlR3VEV36IZX12OfJ8uwXSbmTJlCh1QQ12dpQgwUuNvSfbWB4w==",
"dev": true,
"dependencies": {
"commander": "^9.4.0",
"deepmerge": "^4.2.2",
"fs-extra": "^10.1.0",
"p-debounce": "^4.0.0",
"pkg-up": "^4.0.0",
"semver": "^7.3.7",
"tempy": "^3.0.0",
"vscode-languageserver": "^8.0.2",
"vscode-languageserver-protocol": "^3.17.2",
"vscode-languageserver-textdocument": "1.0.7",
"vscode-uri": "^3.0.3",
"which": "^2.0.2"
},
"bin": {
"typescript-language-server": "lib/cli.js"
},
"engines": {
"node": ">=14.16"
}
},
"node_modules/unique-string": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz",
"integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==",
"dev": true,
"dependencies": {
"crypto-random-string": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true,
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/vscode-jsonrpc": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz",
"integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==",
"dev": true,
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/vscode-languageserver": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.2.tgz",
"integrity": "sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==",
"dev": true,
"dependencies": {
"vscode-languageserver-protocol": "3.17.2"
},
"bin": {
"installServerIntoExtension": "bin/installServerIntoExtension"
}
},
"node_modules/vscode-languageserver-protocol": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz",
"integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==",
"dev": true,
"dependencies": {
"vscode-jsonrpc": "8.0.2",
"vscode-languageserver-types": "3.17.2"
}
},
"node_modules/vscode-languageserver-textdocument": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz",
"integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==",
"dev": true
},
"node_modules/vscode-languageserver-types": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==",
"dev": true
},
"node_modules/vscode-uri": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.4.tgz",
"integrity": "sha512-aEmKD6H8Sg8gaQAUrnadG0BMeWXtiWhRsj1a94n2FYsMkDpgnK7BRVzZjOUYIvkv2B+bp5Bmt4ImZCpYbnJwkg==",
"dev": true
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/yocto-queue": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
"integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
"dev": true,
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
}
},
"dependencies": {
"@types/node": {
"version": "18.8.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.4.tgz",
"integrity": "sha512-WdlVphvfR/GJCLEMbNA8lJ0lhFNBj4SW3O+O5/cEGw9oYrv0al9zTwuQsq+myDUXgNx2jgBynoVgZ2MMJ6pbow==",
"dev": true
},
"commander": {
"version": "9.4.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
"integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==",
"dev": true
},
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"crypto-random-string": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz",
"integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==",
"dev": true,
"requires": {
"type-fest": "^1.0.1"
},
"dependencies": {
"type-fest": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
"dev": true
}
}
},
"daemon": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/daemon/-/daemon-1.1.0.tgz",
"integrity": "sha512-1vX9YVcP21gt12nSD3SQRC/uPU7fyA6M8qyClTBIFuiRWoylFn57PwXhjBAqRl085bZAje7sILhZU48qcS9SWw=="
},
"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"
}
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
},
"docker-modem": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-0.3.7.tgz",
"integrity": "sha512-4Xn4ZVtc/2DEFtxY04lOVeF7yvxwXGVo0sN8FKRBnLhBcwQ78Hb56j+Z5yAXXUhoweVhzGeBeGWahS+af0/mcg==",
"requires": {
"debug": "^2.6.0",
"JSONStream": "0.10.0",
"readable-stream": "~1.0.26-4",
"split-ca": "^1.0.0"
}
},
"find-up": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
"integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
"dev": true,
"requires": {
"locate-path": "^7.1.0",
"path-exists": "^5.0.0"
}
},
"fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
}
},
"graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
}
},
"jsonparse": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz",
"integrity": "sha512-fw7Q/8gFR8iSekUi9I+HqWIap6mywuoe7hQIg3buTVjuZgALKj4HAmm0X6f+TaL4c9NJbvyFQdaI2ppr5p6dnQ=="
},
"JSONStream": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz",
"integrity": "sha512-8XbSFFd43EG+1thjLNFIzCBlwXti0yKa7L+ak/f0T/pkC+31b7G41DXL/JzYpAoYWZ2eCPiu4IIqzijM8N0a/w==",
"requires": {
"jsonparse": "0.0.5",
"through": ">=2.2.7 <3"
}
},
"locate-path": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.1.1.tgz",
"integrity": "sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg==",
"dev": true,
"requires": {
"p-locate": "^6.0.0"
}
},
"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"
}
},
"memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node-docker-api": {
"version": "1.1.22",
"resolved": "https://registry.npmjs.org/node-docker-api/-/node-docker-api-1.1.22.tgz",
"integrity": "sha512-8xfOiuLDJQw+l58i66lUNQhRhS5fAExqQbLolmyqMucrsDON7k7eLMIHphcBwwB7utwCHCQkcp73gSAmzSiAiw==",
"requires": {
"docker-modem": "^0.3.1",
"memorystream": "^0.3.1"
}
},
"p-debounce": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-4.0.0.tgz",
"integrity": "sha512-4Ispi9I9qYGO4lueiLDhe4q4iK5ERK8reLsuzH6BPaXn53EGaua8H66PXIFGrW897hwjXp+pVLrm/DLxN0RF0A==",
"dev": true
},
"p-limit": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
"integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
"dev": true,
"requires": {
"yocto-queue": "^1.0.0"
}
},
"p-locate": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
"integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
"dev": true,
"requires": {
"p-limit": "^4.0.0"
}
},
"path-exists": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
"integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
"dev": true
},
"pkg-up": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-4.0.0.tgz",
"integrity": "sha512-N4zdA4sfOe6yCv+ulPCmpnIBQ5I60xfhDr1otdBBhKte9QtEf3bhfrfkW7dTb+IQ0iEx4ZDzas0kc1o5rdWpYg==",
"dev": true,
"requires": {
"find-up": "^6.2.0"
}
},
"readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"split-ca": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz",
"integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ=="
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
"temp-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
"integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
"dev": true
},
"tempy": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tempy/-/tempy-3.0.0.tgz",
"integrity": "sha512-B2I9X7+o2wOaW4r/CWMkpOO9mdiTRCxXNgob6iGvPmfPWgH/KyUD6Uy5crtWBxIBe3YrNZKR2lSzv1JJKWD4vA==",
"dev": true,
"requires": {
"is-stream": "^3.0.0",
"temp-dir": "^2.0.0",
"type-fest": "^2.12.2",
"unique-string": "^3.0.0"
}
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"type-fest": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
"dev": true
},
"typescript": {
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
"integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
"dev": true
},
"typescript-language-server": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/typescript-language-server/-/typescript-language-server-1.2.0.tgz",
"integrity": "sha512-Ahxko4dKgOY/pGTMdzeVw/NTIZC4z33OqEs7xlR3VEV36IZX12OfJ8uwXSbmTJlCh1QQ12dpQgwUuNvSfbWB4w==",
"dev": true,
"requires": {
"commander": "^9.4.0",
"deepmerge": "^4.2.2",
"fs-extra": "^10.1.0",
"p-debounce": "^4.0.0",
"pkg-up": "^4.0.0",
"semver": "^7.3.7",
"tempy": "^3.0.0",
"vscode-languageserver": "^8.0.2",
"vscode-languageserver-protocol": "^3.17.2",
"vscode-languageserver-textdocument": "1.0.7",
"vscode-uri": "^3.0.3",
"which": "^2.0.2"
}
},
"unique-string": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz",
"integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==",
"dev": true,
"requires": {
"crypto-random-string": "^4.0.0"
}
},
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
},
"vscode-jsonrpc": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.2.tgz",
"integrity": "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==",
"dev": true
},
"vscode-languageserver": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.2.tgz",
"integrity": "sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==",
"dev": true,
"requires": {
"vscode-languageserver-protocol": "3.17.2"
}
},
"vscode-languageserver-protocol": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.2.tgz",
"integrity": "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==",
"dev": true,
"requires": {
"vscode-jsonrpc": "8.0.2",
"vscode-languageserver-types": "3.17.2"
}
},
"vscode-languageserver-textdocument": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz",
"integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==",
"dev": true
},
"vscode-languageserver-types": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz",
"integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==",
"dev": true
},
"vscode-uri": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.4.tgz",
"integrity": "sha512-aEmKD6H8Sg8gaQAUrnadG0BMeWXtiWhRsj1a94n2FYsMkDpgnK7BRVzZjOUYIvkv2B+bp5Bmt4ImZCpYbnJwkg==",
"dev": true
},
"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"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"yocto-queue": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
"integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
"dev": true
}
}
}

View file

@ -1,23 +0,0 @@
{
"name": "reverseproxy",
"version": "1.0.0",
"description": "",
"main": "dist/reverseProxy.js",
"type": "module",
"scripts": {
"build": "tsc",
"proxy": "node dist/reverseProxy.js",
"proxy-daemon": "node dist/reverseProxyDaemon"
},
"author": "Baensch, Kevin",
"license": "MIT",
"devDependencies": {
"@types/node": "^18.8.4",
"typescript": "^4.8.3",
"typescript-language-server": "^1.2.0"
},
"dependencies": {
"daemon": "^1.1.0",
"node-docker-api": "^1.1.22"
}
}

View file

@ -1,44 +0,0 @@
import { Caddy, ContainerData } from "./types";
const caddyConfig: Caddy = {
admin: {
disabled: false,
config: {
persist: false,
},
},
apps: {
http: {
http_port: 80,
https_port: 443,
servers: {},
},
},
};
// shorthand for use in functions
const servers = caddyConfig.apps!.http!.servers;
export function removeServer(id: string) {
if (id in servers) {
delete servers[id];
}
}
export function addServer(container: ContainerData) {
servers[container.Id] = {
listen: container.HostNames,
};
}
export async function updateCaddy(): Promise<void> {
const request = await fetch("google.com");
await request.json();
return;
}
function mkCaddyHost(container: ContainerData, network: string) {
return {
listen: [],
};
}

View file

@ -1,8 +0,0 @@
import * as path from "node:path";
const baseConfPath = "./Config";
export const caddyConfPath = path.join(baseConfPath, "Caddyfile");
export const hostConfPath = path.join(baseConfPath, "hosts");
export const hostConfBakExt = "orig";
export const dockerCaddyName = "caddy2";
export const dockerNetwork = "proxy";

12
src/daemon.d.ts vendored
View file

@ -1,12 +0,0 @@
declare module "daemon" {
export function daemon(
script: string,
args: string[],
opt?: {
stdout?: string,
stderr?: string,
env?: Record<string, string>,
cwd?: string
}
);
}

View file

@ -1,168 +0,0 @@
import { Docker } from "node-docker-api";
import { dockerCaddyName, dockerNetwork, caddyConfPath } from "./const.js";
import {
CaddyState,
ContainerData,
ContainerNetwork,
ContainerOverride,
ImageOverride,
NetworkData,
NetworkOverride,
} from "./types.js";
export let networks: Record<string, NetworkData> = {};
export let containers: Record<string, ContainerData> = {};
export async function update() {
const dockerSock = new Docker({ socketPath: "/var/run/docker.sock" });
await Promise.all([
updateNetworkData(dockerSock),
updateContainerData(dockerSock),
]);
const caddyState = await getCaddyState(dockerSock);
if (caddyState !== "running") await startCaddy(dockerSock, caddyState);
}
async function updateNetworkData(socket: Docker): Promise<void> {
networks = {};
for (const network of (await socket.network.list({
all: true,
})) as unknown as NetworkOverride[]) {
const data = network.data;
// Note: There is no guarantee that Network names don't overlap.
// There are lots of potential issues connected to non unique names so we will throw an error if this is not the case
// See the 'CheckDuplicate' argument here:
// https://docs.docker.com/engine/api/v1.41/#tag/Network/operation/NetworkCreate
if (data.Name in networks)
throw new Error(`ERROR: Duplicate docker network name: ${data.Name}`);
networks[data.Name] = {
Id: data.Id,
Name: data.Name,
Driver: data.Driver,
};
}
return;
}
async function updateContainerData(socket: Docker): Promise<void> {
containers = {};
// The Docker-Node Library is somewhat old and has inacurate/missing typing
for (const container of (await socket.container.list({
all: true,
})) as unknown as ContainerOverride[]) {
const data = container.data;
const networks = Object.values(data.NetworkSettings.Networks).map(
(netData: ContainerNetwork) => {
return [
netData.NetworkID,
{
NetworkID: netData.NetworkID,
IPAddress: netData.IPAddress,
},
] as [string, ContainerNetwork];
}
);
containers[data.Id] = {
Id: data.Id,
Ports: Object.values(data.Ports).map((p) => `${p.PrivatePort}/${p.Type}`),
Name: data.Names[0] ?? "Unnamed",
HostNames: data.Names,
State: data.State,
Networks: Object.fromEntries(networks),
Labels: data.Labels,
};
}
return;
}
async function getCaddyState(socket: Docker): Promise<CaddyState> {
const container = getContainerByName(`/${dockerCaddyName}`);
if (container) {
// Check if container is part of the configured network
const networkCheck = networks[dockerNetwork].Id in container.Networks;
return networkCheck ? container.State : "wrongnetwork";
}
const hasCaddy = (
(await socket.image.list()) as unknown as ImageOverride[]
).some((image) => image?.data?.RepoTags?.includes("caddy:latest"));
return hasCaddy ? "nocontainer" : "noimage";
}
function getContainerByName(containerName: string) {
for (const container of Object.values(containers)) {
if (container.Name === containerName) return container;
}
return undefined;
}
function getNetworkByName(networkName: string) {
for (const network of Object.values(networks)) {
if (network.Name === networkName) return network;
}
return undefined;
}
async function ensureNetwork(socket: Docker) {
if (!Object.values(networks).some((net) => net.Name === dockerNetwork)) {
await socket.network.create({ Name: dockerNetwork });
await updateNetworkData(socket);
}
}
async function addContainerToNetwork(
socket: Docker,
container: ContainerData,
network: NetworkData
) {
if (!(network.Id in container.Networks)) {
await socket.network.get(network.Id).connect({ Container: container.Id });
await updateContainerData(socket);
}
}
async function startCaddy(socket: Docker, caddyState: CaddyState) {
await ensureNetwork(socket);
switch (caddyState) {
case "noimage":
await socket.image.create({}, { fromImage: "caddy", tag: "latest" });
// Create Container in shared network
case "nocontainer":
// Docker Documentation can be found here:
// https://docs.docker.com/engine/api/v1.41/#tag/Container/operation/ContainerCreate
await socket.container.create({
name: dockerCaddyName,
network: dockerNetwork,
Image: "caddy",
HostConfig: {
PortBindings: {
"80": [{ HostPort: "80" }],
"443/tcp": [{ HostIp: "0.0.0.0", HostPort: "443" }],
"443/udp": [{ HostIp: "0.0.0.0", HostPort: "443" }],
"2019/tcp": [{ HostIp: "0.0.0.0", HostPort: "2019" }],
},
Binds: [`${caddyConfPath}:/etc/caddy/Caddyfile`],
},
});
await updateContainerData(socket);
case "wrongnetwork":
await addContainerToNetwork(
socket,
getContainerByName(`/${dockerCaddyName}`)!,
getNetworkByName(dockerNetwork)!
);
case "exited":
const id = getContainerByName(`/${dockerCaddyName}`)?.Id!;
await socket.container.get(id)?.start();
}
}
export async function stopCaddy() {
// Create fresh docker connection (mitigate possible exceptions with the original connection and can be called separately)
const dockerSock = new Docker({ socketPath: "/var/run/docker.sock" });
const container = getContainerByName(`/${dockerCaddyName}`);
if (container?.State === "running")
await dockerSock.container.get(container.Id).stop();
}

View file

@ -1,120 +0,0 @@
import {
accessSync,
constants,
copyFileSync,
existsSync,
readFileSync,
writeFileSync,
} from "node:fs";
import { hostConfPath, hostConfBakExt } from "./const.js";
import { HostData, ContainerData } from "./types.js";
let hasChanged = false;
const hostData: HostData = {};
let initialHostData: HostData = {};
function checkFile(path: string) {
if (!existsSync(path))
throw new Error(`No such file or directory: ${hostConfPath}`);
// Throws error for missing file permissions
accessSync(path, constants.R_OK | constants.W_OK);
}
export function writeConfig(): boolean {
// prevent unnecessary rewrites
if (!hasChanged) return false;
const stringData = (
Object.entries(hostData) as Array<[string, string[]]>
).reduce((prev, [curAddr, curHosts]) => {
return `${prev}${curAddr} ${curHosts.join(" ")}\n`;
}, "");
writeFileSync(hostConfPath, stringData);
hasChanged = false;
return true;
}
// Read initial data from host config backup
function readConfig() {
const textContent = readFileSync(`${hostConfPath}.${hostConfBakExt}`, {
encoding: "utf8",
}) as string;
// NOTE: maybe properly detect EOL-Style if it causes problems
// using Unix for now
for (const line of textContent.split("\n")) {
//skip empty lines and comments
if (!line || line.startsWith("#")) continue;
const { address, hosts } = line.match(/^(?<address>[^\ ]*) (?<hosts>.*)$/)
?.groups ?? { address: "172.0.0.1", hosts: "localhost" };
if (!(address in hostData)) hostData[address] = hosts.split(" ");
else hostData[address] = hostData[address].concat(hosts.split(" "));
}
initialHostData = structuredClone(hostData);
}
export function init() {
// Boilerplate init code
// Check permissions for host and backup file
// conditionally create backup file
checkFile(hostConfPath);
try {
checkFile(`${hostConfPath}.${hostConfBakExt}`);
} catch (err) {
if ((err as Error).message.startsWith("No such file or directory:"))
copyFileSync(hostConfPath, `${hostConfPath}.${hostConfBakExt}`);
else throw err;
}
// load data
readConfig();
}
function addHost(hosts: string | string[], address = "127.0.0.1") {
const hostList = typeof hosts === "string" ? hosts.split(" ") : hosts;
if (!hostData[address]?.some((addr) => hostList.includes(addr))) {
hostData[address] = (hostData[address] ?? []).concat(hostList);
hasChanged = true;
}
}
function removeHost(hosts: string | string[], address = "127.0.0.1") {
if (address in hostData) {
const hostList = typeof hosts === "string" ? hosts.split(" ") : hosts;
hostData[address] = hostData[address].filter(
(host) => !hostList.includes(host)
);
if (hostData[address].length === 0) delete hostData[address];
hasChanged = true;
}
}
export function update(dockerHosts: ContainerData[], networkID: string) {
// Create copy of host list to diff for disconnected containers at the end
const removedHosts = structuredClone(hostData);
// Keep all original hosts in list
for (const address of Object.keys(initialHostData)) {
removedHosts[address] = removedHosts[address].filter(
(hostName) => !initialHostData[address].includes(hostName)
);
}
// Add new containers
for (const container of dockerHosts) {
if (container.State !== "running" || !(networkID in container.Networks))
continue;
const indexAt = removedHosts["127.0.0.1"]?.findIndex(
(host) => host === container.Name
);
if (indexAt !== -1) {
removedHosts["127.0.0.1"].splice(indexAt, 1);
continue;
}
addHost(container.Name);
}
// Remove Containers
for (const address of Object.keys(removedHosts)) {
if (removedHosts[address]?.length > 0)
removeHost(removedHosts[address], address);
}
}

View file

@ -1,43 +0,0 @@
import process from "node:process";
import * as docker from "./docker.js";
import * as hosts from "./hosts.js";
import { dockerNetwork } from "./const.js";
let running = true;
const stopRunning = () => {
running = false;
};
// Signal handlers to terminate min loop
process.on("SIGTERM", stopRunning);
process.on("SIGINT", stopRunning);
hosts.init();
docker.update().then(() => {
hosts.writeConfig();
console.log("Startup Done");
idleMain();
});
async function idleMain() {
// Main Idle Loop
// Checks Docker for changes every ten seconds
// SIGTERM and SIGINT signals can be processed during the timeout so the process can exit gracefully
let idleCount = 0;
const proxyNetworkID = docker.networks[dockerNetwork].Id;
while (running) {
if (idleCount === 0) {
await docker.update();
hosts.update(Object.values(docker.containers), proxyNetworkID);
if (hosts.writeConfig()) {
//update caddy
}
}
await new Promise((res) => setTimeout(res, 1000));
idleCount = (idleCount + 1) % 10;
}
// Cleanup Code goes here (docker shutdown)
await docker.stopCaddy();
}

View file

@ -1,3 +0,0 @@
import { daemon } from "daemon";
daemon("dist/app.js", [], { cwd: process.cwd() });

View file

@ -1,219 +0,0 @@
export type NetType = "Bridge" | "Host" | "none" | "null";
export interface NetworkData {
Id: string;
Name: string;
Driver: NetType;
}
export interface ContainerData {
Id: string;
Name: string;
State: "exited" | "running";
Networks: Record<string, ContainerNetwork>;
HostNames?: string[];
Ports: string[];
Labels: {
HostName?: string;
PortMap?: string[];
};
}
export type ContainerNetwork = {
NetworkID: string;
IPAddress: string;
};
export type ContainerOverride = {
data: {
Id: string;
Names: string[];
State: "exited" | "running";
NetworkSettings: {
Networks: Record<string, ContainerNetwork>;
};
Labels: Record<string, string>;
Ports: {
IP?: string;
PrivatePort: number;
PublicPort?: number;
Type: "tcp" | "udp";
}[];
};
};
export type NetworkOverride = {
data: {
Name: string;
Id: string;
Driver: NetType;
Scope: string;
};
};
export type ImageOverride = {
data: {
Containers: number;
Created: number;
Id: string;
Labels: null | Record<string, string>;
ParentId: string;
RepoDigests: string[];
RepoTags: string[];
SharedSize: number;
Size: number;
VirtualSize: number;
};
};
export type CaddyState =
| "running"
| "exited"
| "nocontainer"
| "noimage"
| "wrongnetwork";
export interface CaddyHttpServer {
listen?: string[];
// "listener_wrappers"?: [{•••}],
read_timeout?: number;
read_header_timeout?: number;
write_timeout?: number;
idle_timeout?: number;
keepalive_interval?: number;
max_header_bytes?: number;
routes?: {
group?: string;
// "match"?: [{••• }],
// "handle"?: [{••• }],
terminal?: boolean;
}[];
errors?: {
routes?: [
{
group?: string;
// "match"?: [{••• }],
// "handle"?: [{••• }],
terminal?: boolean;
}
];
};
tls_connection_policies?: [
{
// "match"?: {••• },
certificate_selection?: {
serial_number?: [{}];
subject_organization?: string[];
public_key_algorithm?: number;
any_tag?: string[];
all_tags?: string[];
};
cipher_suites?: string[];
curves?: string[];
alpn?: string[];
protocol_min?: string;
protocol_max?: string;
client_authentication?: {
trusted_ca_certs?: string[];
trusted_ca_certs_pem_files?: string[];
trusted_leaf_certs?: string;
// "verifiers"?: [{••• }],
mode?: string;
};
default_sni?: string;
insecure_secrets_log?: string;
}
];
automatic_https?: {
disable?: boolean;
disable_redirects?: boolean;
disable_certificates?: boolean;
skip?: string[];
skip_certificates?: string[];
ignore_loaded_certificates?: boolean;
};
strict_sni_host?: boolean;
logs?: {
default_logger_name?: string;
logger_names?: Record<string, string>;
skip_hosts?: string[];
skip_unmapped_hosts?: boolean;
should_log_credentials?: boolean;
};
protocols?: string[];
metrics?: {};
}
export interface CaddyHttp {
http_port: number;
https_port?: number;
grace_period?: number;
shutdown_delay?: number;
servers: Record<string, CaddyHttpServer>;
}
export interface CaddyFileSystem {
module: "file_system";
root: string;
}
export interface Caddy {
admin?: {
/** If true, the admin endpoint will be completely disabled. */
disabled?: boolean;
/** The address to which the admin endpoint's listener should bind itself. */
listen?: string;
enforce_origin?: boolean;
origins?: string[];
config?: {
persist?: boolean;
// "load"?: {••• }
};
identity?: {
identifiers?: string[];
// "issuers"?: [{••• }]
};
remote?: {
listen?: string;
access_control?: [
{
public_keys?: string[];
permissions?: [
{
paths?: string[];
methods?: string[];
}
];
}
];
};
};
logging?: {
sink?: {
// writer?: { }
};
logs?: Record<
string,
{
// "writer"?: { },
// "encoder"?: { },
level?: string;
sampling?: {
interval?: number;
first?: number;
thereafter?: number;
};
include?: string[];
exclude?: string[];
}
>;
};
storage?: {
file_system?: CaddyFileSystem;
};
apps?: {
http?: CaddyHttp;
};
}
export type HostData = Record<string, string[]>;

View file

@ -1,19 +0,0 @@
{
"compilerOptions": {
"target": "esnext",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
// "module": "nodenext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"outDir": "dist"
},
"include": [
"src"
]
}