Init
This commit is contained in:
commit
b852746352
13 changed files with 1612 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
|
.log/
|
||||||
|
Config/hosts*
|
26
Config/Caddyfile
Normal file
26
Config/Caddyfile
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"admin": {▾
|
||||||
|
"disabled": false,
|
||||||
|
"listen": "",
|
||||||
|
"enforce_origin": false,
|
||||||
|
"origins": [""],
|
||||||
|
"config": {
|
||||||
|
"persist": false,
|
||||||
|
"load": {•••}
|
||||||
|
},
|
||||||
|
"identity": {▾
|
||||||
|
"identifiers": [""],
|
||||||
|
"issuers": [{•••}]
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"listen": "",
|
||||||
|
"access_control": [{
|
||||||
|
"public_keys": [""],
|
||||||
|
"permissions": [{
|
||||||
|
"paths": [""],
|
||||||
|
"methods": [""]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
923
package-lock.json
generated
Normal file
923
package-lock.json
generated
Normal file
|
@ -0,0 +1,923 @@
|
||||||
|
{
|
||||||
|
"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
Normal file
23
package.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"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
Normal file
44
src/caddy.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
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: [],
|
||||||
|
};
|
||||||
|
}
|
8
src/const.ts
Normal file
8
src/const.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
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
Normal file
12
src/daemon.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
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
Normal file
168
src/docker.ts
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
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
Normal file
120
src/hosts.ts
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
43
src/reverseProxy.ts
Normal file
43
src/reverseProxy.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
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();
|
||||||
|
}
|
3
src/reverseProxyDaemon.ts
Normal file
3
src/reverseProxyDaemon.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { daemon } from "daemon";
|
||||||
|
|
||||||
|
daemon("dist/app.js", [], { cwd: process.cwd() });
|
219
src/types.ts
Normal file
219
src/types.ts
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
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[]>;
|
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"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