Simplify process by using bash.
This commit is contained in:
parent
b852746352
commit
4679608188
15 changed files with 57 additions and 1612 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,4 +0,0 @@
|
|||
dist/
|
||||
node_modules/
|
||||
.log/
|
||||
Config/hosts*
|
|
@ -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
26
docker-compose.yml
Normal 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
31
hostman.sh
Executable 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
923
package-lock.json
generated
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
23
package.json
23
package.json
|
@ -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"
|
||||
}
|
||||
}
|
44
src/caddy.ts
44
src/caddy.ts
|
@ -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: [],
|
||||
};
|
||||
}
|
|
@ -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
12
src/daemon.d.ts
vendored
|
@ -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
|
||||
}
|
||||
);
|
||||
}
|
168
src/docker.ts
168
src/docker.ts
|
@ -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();
|
||||
}
|
120
src/hosts.ts
120
src/hosts.ts
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
import { daemon } from "daemon";
|
||||
|
||||
daemon("dist/app.js", [], { cwd: process.cwd() });
|
219
src/types.ts
219
src/types.ts
|
@ -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[]>;
|
|
@ -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"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue