From 4679608188796a6408e597c279300af4ce481534 Mon Sep 17 00:00:00 2001 From: Kevin Baensch Date: Fri, 4 Nov 2022 13:01:36 +0100 Subject: [PATCH] Simplify process by using bash. --- .gitignore | 4 - Config/Caddyfile | 26 -- docker-compose.yml | 26 ++ hostman.sh | 31 ++ package-lock.json | 923 -------------------------------------- package.json | 23 - src/caddy.ts | 44 -- src/const.ts | 8 - src/daemon.d.ts | 12 - src/docker.ts | 168 ------- src/hosts.ts | 120 ----- src/reverseProxy.ts | 43 -- src/reverseProxyDaemon.ts | 3 - src/types.ts | 219 --------- tsconfig.json | 19 - 15 files changed, 57 insertions(+), 1612 deletions(-) delete mode 100644 Config/Caddyfile create mode 100644 docker-compose.yml create mode 100755 hostman.sh delete mode 100644 package-lock.json delete mode 100644 package.json delete mode 100644 src/caddy.ts delete mode 100644 src/const.ts delete mode 100644 src/daemon.d.ts delete mode 100644 src/docker.ts delete mode 100644 src/hosts.ts delete mode 100644 src/reverseProxy.ts delete mode 100644 src/reverseProxyDaemon.ts delete mode 100644 src/types.ts delete mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index ee0d57b..e69de29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +0,0 @@ -dist/ -node_modules/ -.log/ -Config/hosts* diff --git a/Config/Caddyfile b/Config/Caddyfile deleted file mode 100644 index dd8775d..0000000 --- a/Config/Caddyfile +++ /dev/null @@ -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": [""] - }] - }] - } - } -} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e200557 --- /dev/null +++ b/docker-compose.yml @@ -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 diff --git a/hostman.sh b/hostman.sh new file mode 100755 index 0000000..792c981 --- /dev/null +++ b/hostman.sh @@ -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 diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 64eb5cb..0000000 --- a/package-lock.json +++ /dev/null @@ -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 - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 787fac3..0000000 --- a/package.json +++ /dev/null @@ -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" - } -} diff --git a/src/caddy.ts b/src/caddy.ts deleted file mode 100644 index 0b3a409..0000000 --- a/src/caddy.ts +++ /dev/null @@ -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 { - const request = await fetch("google.com"); - await request.json(); - return; -} - -function mkCaddyHost(container: ContainerData, network: string) { - return { - listen: [], - }; -} diff --git a/src/const.ts b/src/const.ts deleted file mode 100644 index 6ba80ee..0000000 --- a/src/const.ts +++ /dev/null @@ -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"; diff --git a/src/daemon.d.ts b/src/daemon.d.ts deleted file mode 100644 index 62b2d10..0000000 --- a/src/daemon.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare module "daemon" { - export function daemon( - script: string, - args: string[], - opt?: { - stdout?: string, - stderr?: string, - env?: Record, - cwd?: string - } - ); -} diff --git a/src/docker.ts b/src/docker.ts deleted file mode 100644 index 7599780..0000000 --- a/src/docker.ts +++ /dev/null @@ -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 = {}; -export let containers: Record = {}; - -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 { - 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 { - 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 { - 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(); -} diff --git a/src/hosts.ts b/src/hosts.ts deleted file mode 100644 index 9ed5dd8..0000000 --- a/src/hosts.ts +++ /dev/null @@ -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(/^(?
[^\ ]*) (?.*)$/) - ?.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); - } -} diff --git a/src/reverseProxy.ts b/src/reverseProxy.ts deleted file mode 100644 index 049feff..0000000 --- a/src/reverseProxy.ts +++ /dev/null @@ -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(); -} diff --git a/src/reverseProxyDaemon.ts b/src/reverseProxyDaemon.ts deleted file mode 100644 index 69b8256..0000000 --- a/src/reverseProxyDaemon.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { daemon } from "daemon"; - -daemon("dist/app.js", [], { cwd: process.cwd() }); diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 31cdb57..0000000 --- a/src/types.ts +++ /dev/null @@ -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; - 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; - }; - Labels: Record; - 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; - 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; - 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; -} - -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; diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index cfcd0f0..0000000 --- a/tsconfig.json +++ /dev/null @@ -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" - ] -}