nginx #2
9 changed files with 530 additions and 92 deletions
343
deno.lock
generated
343
deno.lock
generated
|
@ -1,10 +1,338 @@
|
|||
{
|
||||
"version": "3",
|
||||
"packages": {
|
||||
"specifiers": {
|
||||
"npm:@deepkit/type@1.0.1-alpha.97": "npm:@deepkit/type@1.0.1-alpha.97_@deepkit+core@1.0.1-alpha.108",
|
||||
"npm:@effect/schema@0.36.5": "npm:@effect/schema@0.36.5_@effect+data@0.18.7_@effect+io@0.40.3__@effect+data@0.18.7",
|
||||
"npm:@ovh-api/api": "npm:@ovh-api/api@4.1.3",
|
||||
"npm:@ovh-api/domain": "npm:@ovh-api/domain@4.0.3",
|
||||
"npm:@sinclair/typebox@0.31.17": "npm:@sinclair/typebox@0.31.17",
|
||||
"npm:ajv@8.12.0": "npm:ajv@8.12.0",
|
||||
"npm:arktype@1.0.21-alpha": "npm:arktype@1.0.21-alpha",
|
||||
"npm:io-ts@2.2.20": "npm:io-ts@2.2.20_fp-ts@2.16.1",
|
||||
"npm:joi@17.10.2": "npm:joi@17.10.2",
|
||||
"npm:ovh-es": "npm:ovh-es@1.7.0",
|
||||
"npm:ow@0.28.2": "npm:ow@0.28.2",
|
||||
"npm:runtypes@6.7.0": "npm:runtypes@6.7.0",
|
||||
"npm:superstruct@1.0.3": "npm:superstruct@1.0.3",
|
||||
"npm:yup@1.3.2": "npm:yup@1.3.2"
|
||||
},
|
||||
"npm": {
|
||||
"@deepkit/core@1.0.1-alpha.108": {
|
||||
"integrity": "sha512-4nN9qL7OSG8kAvhI4aNVGSADgLK7ZPetISfTq7LGSWZJGnT4hGi+/Dxd2bW3KYrUZ4NRP+e/N3IUaQBkSAJ6Pw==",
|
||||
"dependencies": {
|
||||
"dot-prop": "dot-prop@5.3.0",
|
||||
"to-fast-properties": "to-fast-properties@3.0.1"
|
||||
}
|
||||
},
|
||||
"@deepkit/type-spec@1.0.1-alpha.108": {
|
||||
"integrity": "sha512-OIJsZ0nZKybaKrzrY7WpkIlDXm88wE8N5G5cu+FL3snZx/drzF5FxmbRP2omLGRRDb68+o/vTni26sUbBtWOBw==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@deepkit/type@1.0.1-alpha.97_@deepkit+core@1.0.1-alpha.108": {
|
||||
"integrity": "sha512-fnMrhMVYANyZ8zrKEj7KnJMTl2WhXKza9dh9s0Mtgcowd73YSJyEdvFkBKcabmHbvlbHFkAHv8KAvYifvWbGvw==",
|
||||
"dependencies": {
|
||||
"@deepkit/core": "@deepkit/core@1.0.1-alpha.108",
|
||||
"@deepkit/type-spec": "@deepkit/type-spec@1.0.1-alpha.108",
|
||||
"@types/uuid": "@types/uuid@8.3.4",
|
||||
"buffer": "buffer@5.7.1",
|
||||
"uuid": "uuid@8.3.2"
|
||||
}
|
||||
},
|
||||
"@effect/data@0.18.7": {
|
||||
"integrity": "sha512-r7C9VjavmG85wb5BOvcbbKGioPJCoBAFsJVOUNWlxZBRIU+l68ENpsyzCkWsU7dP4teAztjBZ89O3hVhBX0Huw==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@effect/io@0.40.3_@effect+data@0.18.7": {
|
||||
"integrity": "sha512-bnHBFq1XzXn94x2w5FcXZz3MbY7N3YrhiI2CrncJr3WcGRDc2rCYIpPupw0JQGFcJsoopTj1BNfBuBR5s4/RyA==",
|
||||
"dependencies": {
|
||||
"@effect/data": "@effect/data@0.18.7"
|
||||
}
|
||||
},
|
||||
"@effect/schema@0.36.5_@effect+data@0.18.7_@effect+io@0.40.3__@effect+data@0.18.7": {
|
||||
"integrity": "sha512-E8KZ17DqZJl7E/eEVTkxb2NEv6vYhab79HugHi10krd2Gm3vOJvWs+nRgtPhI+0dvkXVxzCcY8bLfkND2F0rBg==",
|
||||
"dependencies": {
|
||||
"@effect/data": "@effect/data@0.18.7",
|
||||
"@effect/io": "@effect/io@0.40.3_@effect+data@0.18.7",
|
||||
"fast-check": "fast-check@3.14.0"
|
||||
}
|
||||
},
|
||||
"@hapi/hoek@9.3.0": {
|
||||
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@hapi/topo@5.1.0": {
|
||||
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "@hapi/hoek@9.3.0"
|
||||
}
|
||||
},
|
||||
"@ovh-api/api@4.1.3": {
|
||||
"integrity": "sha512-gRnlqLEolPj2thBHt7tlM0z1tPNc86PSmOy3jkmOr46hAY+eHI/mGlTInIAJknc9iDSqZ9eIVzUiNngtjysYAw==",
|
||||
"dependencies": {
|
||||
"@ovh-api/common": "@ovh-api/common@4.0.2",
|
||||
"open": "open@8.4.2"
|
||||
}
|
||||
},
|
||||
"@ovh-api/common@4.0.2": {
|
||||
"integrity": "sha512-9PKJjtq7l2mP1t6Ta+cEYZKF3UkHtR1P6f5xvH+M78Hgj7HMwX2vxByuf5FkipOeb3Elfq8ASwZxSiP5+wMP7g==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@ovh-api/domain@4.0.3": {
|
||||
"integrity": "sha512-ARUCOicVekcXmXAUV03aFqXGoHpYow3jyvdqq8e7k3ftXtvkoR1UQXX4rWGXdWgxW7rA7ooDWcU+vGm/jYQqgQ==",
|
||||
"dependencies": {
|
||||
"@ovh-api/common": "@ovh-api/common@4.0.2"
|
||||
}
|
||||
},
|
||||
"@sideway/address@4.1.4": {
|
||||
"integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "@hapi/hoek@9.3.0"
|
||||
}
|
||||
},
|
||||
"@sideway/formula@3.0.1": {
|
||||
"integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@sideway/pinpoint@2.0.0": {
|
||||
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@sinclair/typebox@0.31.17": {
|
||||
"integrity": "sha512-GVYVHHOGINx+DT2DwjXoCQO0mRpztYKyb3d48tucuqhjhHpQYGp7Xx7dhhQGzILx/beuBrzfITMC7/5X7fw+UA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@sindresorhus/is@4.6.0": {
|
||||
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"@types/uuid@8.3.4": {
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"ajv@8.12.0": {
|
||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "fast-deep-equal@3.1.3",
|
||||
"json-schema-traverse": "json-schema-traverse@1.0.0",
|
||||
"require-from-string": "require-from-string@2.0.2",
|
||||
"uri-js": "uri-js@4.4.1"
|
||||
}
|
||||
},
|
||||
"arktype@1.0.21-alpha": {
|
||||
"integrity": "sha512-XQBoepICSrwDXYlh7gqcrKWEbWTSebToIoTimi9CxVLLlxNWt/YXNrKrSITr/T9jke+TIag1tUcIum/90EQNpg==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"base64-js@1.5.1": {
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"buffer@5.7.1": {
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"dependencies": {
|
||||
"base64-js": "base64-js@1.5.1",
|
||||
"ieee754": "ieee754@1.2.1"
|
||||
}
|
||||
},
|
||||
"callsites@3.1.0": {
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"debug@2.6.9": {
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "ms@2.0.0"
|
||||
}
|
||||
},
|
||||
"define-lazy-prop@2.0.0": {
|
||||
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"dot-prop@5.3.0": {
|
||||
"integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
|
||||
"dependencies": {
|
||||
"is-obj": "is-obj@2.0.0"
|
||||
}
|
||||
},
|
||||
"dot-prop@6.0.1": {
|
||||
"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
|
||||
"dependencies": {
|
||||
"is-obj": "is-obj@2.0.0"
|
||||
}
|
||||
},
|
||||
"fast-check@3.14.0": {
|
||||
"integrity": "sha512-9Z0zqASzDNjXBox/ileV/fd+4P+V/f3o4shM6QawvcdLFh8yjPG4h5BrHUZ8yzY6amKGDTAmRMyb/JZqe+dCgw==",
|
||||
"dependencies": {
|
||||
"pure-rand": "pure-rand@6.0.4"
|
||||
}
|
||||
},
|
||||
"fast-deep-equal@3.1.3": {
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"fp-ts@2.16.1": {
|
||||
"integrity": "sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"ieee754@1.2.1": {
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"io-ts@2.2.20_fp-ts@2.16.1": {
|
||||
"integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==",
|
||||
"dependencies": {
|
||||
"fp-ts": "fp-ts@2.16.1"
|
||||
}
|
||||
},
|
||||
"is-docker@2.2.1": {
|
||||
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"is-obj@2.0.0": {
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"is-wsl@2.2.0": {
|
||||
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
||||
"dependencies": {
|
||||
"is-docker": "is-docker@2.2.1"
|
||||
}
|
||||
},
|
||||
"joi@17.10.2": {
|
||||
"integrity": "sha512-hcVhjBxRNW/is3nNLdGLIjkgXetkeGc2wyhydhz8KumG23Aerk4HPjU5zaPAMRqXQFc0xNqXTC7+zQjxr0GlKA==",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "@hapi/hoek@9.3.0",
|
||||
"@hapi/topo": "@hapi/topo@5.1.0",
|
||||
"@sideway/address": "@sideway/address@4.1.4",
|
||||
"@sideway/formula": "@sideway/formula@3.0.1",
|
||||
"@sideway/pinpoint": "@sideway/pinpoint@2.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse@1.0.0": {
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"lodash.isequal@4.5.0": {
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"mout@1.2.4": {
|
||||
"integrity": "sha512-mZb9uOruMWgn/fw28DG4/yE3Kehfk1zKCLhuDU2O3vlKdnBBr4XaOCqVTflJ5aODavGUPqFHZgrFX3NJVuxGhQ==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"ms@2.0.0": {
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"nyks@6.10.0": {
|
||||
"integrity": "sha512-Y65Kzo+A9b+BzsGBSfpjdm1a496sH564gHZ1anw8yNA+Ki9u2KC4EJuDQCSTbNliE1g76YsxAs6SWKXhZDsbJA==",
|
||||
"dependencies": {
|
||||
"mout": "mout@1.2.4"
|
||||
}
|
||||
},
|
||||
"open@8.4.2": {
|
||||
"integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
|
||||
"dependencies": {
|
||||
"define-lazy-prop": "define-lazy-prop@2.0.0",
|
||||
"is-docker": "is-docker@2.2.1",
|
||||
"is-wsl": "is-wsl@2.2.0"
|
||||
}
|
||||
},
|
||||
"ovh-es@1.7.0": {
|
||||
"integrity": "sha512-om96fYG7JpCfDyegVynDpkmIixMsqPkDb8V3Mz7i+7sC9NPxNwe9icRrBzexcDvMstJH0t7QnesRHDPuA2hMwg==",
|
||||
"dependencies": {
|
||||
"debug": "debug@2.6.9",
|
||||
"mout": "mout@1.2.4",
|
||||
"nyks": "nyks@6.10.0"
|
||||
}
|
||||
},
|
||||
"ow@0.28.2": {
|
||||
"integrity": "sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "@sindresorhus/is@4.6.0",
|
||||
"callsites": "callsites@3.1.0",
|
||||
"dot-prop": "dot-prop@6.0.1",
|
||||
"lodash.isequal": "lodash.isequal@4.5.0",
|
||||
"vali-date": "vali-date@1.0.0"
|
||||
}
|
||||
},
|
||||
"property-expr@2.0.6": {
|
||||
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"punycode@2.3.0": {
|
||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"pure-rand@6.0.4": {
|
||||
"integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"require-from-string@2.0.2": {
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"runtypes@6.7.0": {
|
||||
"integrity": "sha512-3TLdfFX8YHNFOhwHrSJza6uxVBmBrEjnNQlNXvXCdItS0Pdskfg5vVXUTWIN+Y23QR09jWpSl99UHkA83m4uWA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"superstruct@1.0.3": {
|
||||
"integrity": "sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"tiny-case@1.0.3": {
|
||||
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"to-fast-properties@3.0.1": {
|
||||
"integrity": "sha512-/wtNi1tW1F3nf0OL6AqVxGw9Tr1ET70InMhJuVxPwFdGqparF0nQ4UWGLf2DsoI2bFDtthlBnALncZpUzOnsUw==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"toposort@2.0.2": {
|
||||
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"type-fest@2.19.0": {
|
||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"uri-js@4.4.1": {
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dependencies": {
|
||||
"punycode": "punycode@2.3.0"
|
||||
}
|
||||
},
|
||||
"uuid@8.3.2": {
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"vali-date@1.0.0": {
|
||||
"integrity": "sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"yup@1.3.2": {
|
||||
"integrity": "sha512-6KCM971iQtJ+/KUaHdrhVr2LDkfhBtFPRnsG1P8F4q3uUVQ2RfEM9xekpha9aA4GXWJevjM10eDcPQ1FfWlmaQ==",
|
||||
"dependencies": {
|
||||
"property-expr": "property-expr@2.0.6",
|
||||
"tiny-case": "tiny-case@1.0.3",
|
||||
"toposort": "toposort@2.0.2",
|
||||
"type-fest": "type-fest@2.19.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"redirects": {
|
||||
"https://deno.land/x/typeschema/mod.ts": "https://deno.land/x/typeschema@v0.12.1/mod.ts",
|
||||
"https://deno.land/x/validasaur/mod.ts": "https://deno.land/x/validasaur@v0.15.0/mod.ts",
|
||||
"https://deno.land/x/zod/mod.ts": "https://deno.land/x/zod@v3.22.4/mod.ts"
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/std@0.208.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee",
|
||||
"https://deno.land/std@0.208.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56",
|
||||
"https://deno.land/std@0.208.0/bytes/concat.ts": "d3d420badeb4f26a0f2f3ce343725f937326aff1b4634b25341b12b27353aac4",
|
||||
"https://deno.land/std@0.208.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219",
|
||||
"https://deno.land/std@0.208.0/encoding/_util.ts": "f368920189c4fe6592ab2e93bd7ded8f3065b84f95cd3e036a4a10a75649dcba",
|
||||
"https://deno.land/std@0.208.0/encoding/hex.ts": "a384101d02cd87036c708f540825feb5b073c8527a00d635e48b2e69c992a5f9",
|
||||
"https://deno.land/std@0.208.0/io/buffer.ts": "11acaeae3dc0e491a335d82915e09e9f8afd53ecb82562515e5951e78f69b076",
|
||||
"https://deno.land/std@0.208.0/path/_common/assert_path.ts": "061e4d093d4ba5aebceb2c4da3318bfe3289e868570e9d3a8e327d91c2958946",
|
||||
"https://deno.land/std@0.208.0/path/_common/basename.ts": "0d978ff818f339cd3b1d09dc914881f4d15617432ae519c1b8fdc09ff8d3789a",
|
||||
|
@ -108,6 +436,19 @@
|
|||
"https://deno.land/std@0.208.0/streams/writable_stream_from_writer.ts": "057bdfc6c08e34a8a86e2d61efe7354a8a0976260cd1437de8b7e64bcefaa9b9",
|
||||
"https://deno.land/std@0.208.0/streams/write_all.ts": "8fc9525c16eb60eb851274d4693ecd35c2177620239fbdfa8f5aacb32702f2cb",
|
||||
"https://deno.land/std@0.208.0/streams/writer_from_stream_writer.ts": "71d7a26f2a2b955794a7318856ad64d9eade36467d930b40698d3d5bfb0ce3b4",
|
||||
"https://deno.land/std@0.208.0/streams/zip_readable_streams.ts": "721c5bce8862c8225e60995b2d61c7b1b1d5b5178b60d303a01f453d5c26bb62"
|
||||
"https://deno.land/std@0.208.0/streams/zip_readable_streams.ts": "721c5bce8862c8225e60995b2d61c7b1b1d5b5178b60d303a01f453d5c26bb62",
|
||||
"https://deno.land/x/zod@v3.22.4/ZodError.ts": "4de18ff525e75a0315f2c12066b77b5c2ae18c7c15ef7df7e165d63536fdf2ea",
|
||||
"https://deno.land/x/zod@v3.22.4/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef",
|
||||
"https://deno.land/x/zod@v3.22.4/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/parseUtil.ts": "f791e6e65a0340d85ad37d26cd7a3ba67126cd9957eac2b7163162155283abb1",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/util.ts": "8baf19b19b2fca8424380367b90364b32503b6b71780269a6e3e67700bb02774",
|
||||
"https://deno.land/x/zod@v3.22.4/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268",
|
||||
"https://deno.land/x/zod@v3.22.4/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c",
|
||||
"https://deno.land/x/zod@v3.22.4/mod.ts": "64e55237cb4410e17d968cd08975566059f27638ebb0b86048031b987ba251c4",
|
||||
"https://deno.land/x/zod@v3.22.4/types.ts": "724185522fafe43ee56a52333958764c8c8cd6ad4effa27b42651df873fc151e"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#!/bin/env -S deno run -A --unstable
|
||||
|
||||
import { daemon_send, new_cmd_disable, new_cmd_enable, new_cmd_status, new_cmd_stop } from "./src/lib.ts";
|
||||
import { load_all_container_configs, new_container_config, save_container_config } from "./src/lib/config.ts";
|
||||
import { ContainerConfig } from "./src/lib/config.ts";
|
||||
import { load_base, new_container_context } from "./src/lib/create.ts";
|
||||
import { container_paths, socket_path } from "./src/lib/paths.ts";
|
||||
import { async_collect } from "./src/lib/utils.ts";
|
||||
import { log_from, run } from "./src/lib/utils.ts";
|
||||
|
||||
const log = log_from("control");
|
||||
|
@ -78,16 +79,16 @@ Commands:
|
|||
export async function create(name: string, base_name: string) {
|
||||
log("loading base", base_name);
|
||||
const base = await load_base(base_name);
|
||||
const known_containers = await load_all_container_configs();
|
||||
const known_containers = await async_collect(ContainerConfig.load_all());
|
||||
|
||||
const paths = container_paths(name);
|
||||
await Deno.mkdir(paths.base);
|
||||
const configuration = new_container_config(name);
|
||||
const configuration = ContainerConfig.new_default(name);
|
||||
|
||||
log("creating the container", name, "at", paths.base);
|
||||
const context = new_container_context(paths.root, configuration, known_containers);
|
||||
await Deno.mkdir(paths.root);
|
||||
await run("sudo", "chown", "root:root", paths.root);
|
||||
await base.build(context);
|
||||
await save_container_config(configuration);
|
||||
await configuration.save();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/env -S deno run -A --unstable
|
||||
|
||||
import { daemon_listen, Runner, start_runner } from "./src/lib.ts";
|
||||
import { load_container_config } from "./src/lib/config.ts";
|
||||
import { daemon_listen, Runner } from "./src/lib.ts";
|
||||
import { ContainerConfig } from "./src/lib/config.ts";
|
||||
import { socket_path, state_path } from "./src/lib/paths.ts";
|
||||
import { log_from, sleep } from "./src/lib/utils.ts";
|
||||
|
||||
|
@ -93,10 +93,12 @@ async function create_state() {
|
|||
async enable(name: string) {
|
||||
if (self.enabled.has(name)) throw new Error("Container already enabled");
|
||||
log("loading container", name);
|
||||
const config = await load_container_config(name); // TODO
|
||||
const config = await ContainerConfig.load(name); // TODO
|
||||
if (config === null) throw new Error("can't read config");
|
||||
log("starting container", name);
|
||||
self.enabled.set(name, await start_runner(config));
|
||||
const runner = new Runner(config);
|
||||
runner.start();
|
||||
self.enabled.set(name, runner);
|
||||
log("container", name, "started");
|
||||
},
|
||||
async disable(name: string) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { lines, log_from, loop_process, run } from "./lib/utils.ts";
|
|||
import { ContainerConfig } from "./lib/config.ts";
|
||||
import { container_paths } from "./lib/paths.ts";
|
||||
import { container_command } from "./lib/nspawn.ts";
|
||||
import { LoopProcess } from "./lib/utils.ts";
|
||||
|
||||
const log = log_from("lib");
|
||||
|
||||
|
@ -66,28 +67,36 @@ export async function daemon_send(sock_path: string, command: Cmd) {
|
|||
return await toText(request.readable);
|
||||
}
|
||||
|
||||
export type Runner = Awaited<ReturnType<typeof start_runner>>;
|
||||
export function start_runner(config: ContainerConfig) {
|
||||
const { name } = config;
|
||||
export class Runner {
|
||||
name;
|
||||
config;
|
||||
loop: LoopProcess | null;
|
||||
|
||||
constructor(config: ContainerConfig) {
|
||||
this.name = config.name;
|
||||
this.config = config;
|
||||
this.loop = null;
|
||||
}
|
||||
|
||||
start() {
|
||||
const paths = container_paths(name);
|
||||
const command = container_command(name, paths.root, {
|
||||
boot: true,
|
||||
veth: true,
|
||||
ports: config.redirects,
|
||||
redirections: this.config.redirections,
|
||||
cmd_opts: {
|
||||
stdin: "null",
|
||||
stdout: "null",
|
||||
},
|
||||
syscall_filter: ["add_key", "keyctl", "bpf"],
|
||||
});
|
||||
const container_loop = loop_process(command, {
|
||||
this.loop = loop_process(command, {
|
||||
on_start: () => log("container", name, "started"),
|
||||
on_stop: () => log("container", name, "stopped"),
|
||||
});
|
||||
return {
|
||||
name,
|
||||
config,
|
||||
container_loop,
|
||||
stop: () => container_loop.kill(),
|
||||
};
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.loop?.kill();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +1,9 @@
|
|||
import { container_paths, containers_path, state_config_path } from "./paths.ts";
|
||||
import { exists, log_from } from "./utils.ts";
|
||||
import { log_from } from "./utils.ts";
|
||||
import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
|
||||
|
||||
const log = log_from("config");
|
||||
|
||||
export function new_container_config(name: string): ContainerConfig {
|
||||
return {
|
||||
name,
|
||||
version: 0,
|
||||
redirects: [] as [number, number][],
|
||||
};
|
||||
}
|
||||
|
||||
export type ContainerConfig = ReturnType<typeof parse_container_config>;
|
||||
export function parse_container_config(json: string) {
|
||||
return z.object({
|
||||
name: z.string(),
|
||||
version: z.number(),
|
||||
redirects: z.array(
|
||||
z.tuple([
|
||||
z.number(),
|
||||
z.number(),
|
||||
]).or(z.tuple([
|
||||
z.number(),
|
||||
z.number(),
|
||||
z.literal("tcp").or(z.literal("udp")),
|
||||
])),
|
||||
),
|
||||
}).parse(JSON.parse(json));
|
||||
}
|
||||
|
||||
export async function load_container_config(name: string) {
|
||||
const config_path = container_paths(name).configuration;
|
||||
log("loading config for", name);
|
||||
if (!exists(config_path)) return null;
|
||||
const content = await Deno.readTextFile(config_path);
|
||||
const read = parse_container_config(content);
|
||||
const default_ = new_container_config(name);
|
||||
if (read.version < default_.version) throw new Error("read conf version is outdated");
|
||||
return { ...default_, ...read } as ContainerConfig;
|
||||
}
|
||||
|
||||
export async function save_container_config(config: ContainerConfig) {
|
||||
log("saving config of", config.name);
|
||||
const config_path = container_paths(config.name).configuration;
|
||||
const serialized = JSON.stringify(config, null, 4);
|
||||
await Deno.writeTextFile(config_path, serialized);
|
||||
}
|
||||
|
||||
export async function load_all_container_configs() {
|
||||
const names = Array.from(Deno.readDirSync(containers_path()))
|
||||
.filter((e) => e.isDirectory)
|
||||
.map((e) => e.name);
|
||||
const results = await Promise.all(names.map((name) => load_container_config(name)));
|
||||
return results.filter((item) => item != null) as ContainerConfig[];
|
||||
}
|
||||
|
||||
export type StateConfig = ReturnType<typeof new_config>;
|
||||
export function new_config(app_key: string, app_secret: string, consumer_key: string) {
|
||||
return { app_key, app_secret, consumer_key };
|
||||
|
@ -72,3 +20,87 @@ export async function load_state_config() {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const CONTAINER_CONFIG_VERSION = 1;
|
||||
|
||||
export class ContainerConfig {
|
||||
name;
|
||||
redirections;
|
||||
|
||||
constructor(name: string, redirections: ContainerConfigRedirection[]) {
|
||||
this.name = name;
|
||||
this.redirections = redirections;
|
||||
}
|
||||
|
||||
public static new_default(name: string) {
|
||||
return new ContainerConfig(name, []);
|
||||
}
|
||||
|
||||
public static async load(name: string) {
|
||||
const path = container_paths(name).configuration;
|
||||
const content = await Deno.readTextFile(path);
|
||||
return ContainerConfig.deserialize(content);
|
||||
}
|
||||
|
||||
public async save() {
|
||||
const path = container_paths(this.name).configuration;
|
||||
await Deno.writeTextFile(path, this.serialize());
|
||||
}
|
||||
|
||||
public static async *load_all() {
|
||||
for await (const { isDirectory, name } of Deno.readDir(containers_path())) {
|
||||
if (!isDirectory) continue;
|
||||
yield await ContainerConfig.load(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static deserialize(raw: string) {
|
||||
const unknown = JSON.parse(raw);
|
||||
const parsed = parse(unknown);
|
||||
return new ContainerConfig(parsed.name, parsed.redirections);
|
||||
}
|
||||
|
||||
public serialize() {
|
||||
const raw: SerializedContainerConfig = {
|
||||
version: CONTAINER_CONFIG_VERSION,
|
||||
name: this.name,
|
||||
redirections: this.redirections,
|
||||
};
|
||||
return JSON.stringify(raw);
|
||||
}
|
||||
|
||||
public *used_host_ports() {
|
||||
for (const redir of this.redirections) {
|
||||
if (redir.kind === "http") yield redir.port;
|
||||
if (redir.kind === "port") yield redir.from;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parse(input: unknown) {
|
||||
const redir_port = z.object({
|
||||
kind: z.literal("port"),
|
||||
from: z.number(),
|
||||
to: z.number(),
|
||||
});
|
||||
|
||||
const redir_http = z.object({
|
||||
kind: z.literal("http"),
|
||||
tls: z.boolean(),
|
||||
port: z.number(),
|
||||
domain: z.string(),
|
||||
});
|
||||
|
||||
// TODO : redir DNS SRV
|
||||
|
||||
const redirection = redir_http.or(redir_port);
|
||||
|
||||
return z.object({
|
||||
name: z.string(),
|
||||
version: z.number(),
|
||||
redirections: z.array(redirection),
|
||||
}).parse(input);
|
||||
}
|
||||
|
||||
type SerializedContainerConfig = ReturnType<typeof parse>;
|
||||
export type ContainerConfigRedirection = SerializedContainerConfig["redirections"][0];
|
||||
|
|
|
@ -37,11 +37,11 @@ export function new_container_context(root_dir: string, config: ContainerConfig,
|
|||
},
|
||||
redirect: (from: number, to: number) => {
|
||||
log("redirects", from, "to", to);
|
||||
config.redirects.push([from, to]);
|
||||
config.redirections.push({ kind: "port", from, to });
|
||||
},
|
||||
available_port: (target: number) => {
|
||||
const used_by_known_containers = known_containers.map((c) => c.redirects[0]).flat();
|
||||
const used_by_self = config.redirects.map((r) => r[0]);
|
||||
const used_by_known_containers = known_containers.map((c) => [...c.used_host_ports()]).flat();
|
||||
const used_by_self = config.used_host_ports();
|
||||
const used = [...used_by_known_containers, ...used_by_self];
|
||||
let result = target;
|
||||
while (used.includes(result)) result += 1;
|
||||
|
|
42
instance/src/lib/nginx.ts
Normal file
42
instance/src/lib/nginx.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { run } from "./utils.ts";
|
||||
import * as path from "https://deno.land/std@0.214.0/path/mod.ts";
|
||||
|
||||
class NginxController {
|
||||
proxy_target_url;
|
||||
enabled_conf_dir;
|
||||
|
||||
constructor(proxy_target_url: string, enabled_conf_dir: string) {
|
||||
this.proxy_target_url = proxy_target_url;
|
||||
this.enabled_conf_dir = enabled_conf_dir;
|
||||
}
|
||||
|
||||
public async add_proxy(url: string, port: number, conf_dir: string) {
|
||||
const conf_file_content = `
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name ${url};
|
||||
location / {
|
||||
proxy_pass http://${this.proxy_target_url}:${port};
|
||||
}
|
||||
}
|
||||
`;
|
||||
const conf_file_path = path.join(conf_dir, url + ".conf");
|
||||
const enabled_conf_file_path = path.join(this.enabled_conf_dir, url + ".conf");
|
||||
await Deno.writeTextFile(conf_file_path, conf_file_content);
|
||||
await run("ln", "-s", await Deno.realPath(conf_file_path), enabled_conf_file_path);
|
||||
await this.reload();
|
||||
}
|
||||
|
||||
public async remove_proxy(url: string, conf_dir: string) {
|
||||
const conf_file_path = path.join(conf_dir, url + ".conf");
|
||||
const enabled_conf_file_path = path.join(this.enabled_conf_dir, url + ".conf");
|
||||
await Deno.remove(enabled_conf_file_path);
|
||||
await Deno.remove(conf_file_path);
|
||||
await this.reload();
|
||||
}
|
||||
|
||||
private async reload() {
|
||||
await run("systemctl", "restart", "nginx");
|
||||
}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
// wrapper
|
||||
|
||||
import { log_from, sleep } from "./utils.ts";
|
||||
import { ContainerConfigRedirection } from "./config.ts";
|
||||
|
||||
const log = log_from("nspawn");
|
||||
|
||||
export function container_command(name: string, directory: string, opts?: {
|
||||
veth?: boolean;
|
||||
boot?: boolean;
|
||||
ports?: ([number, number] | [number, number, "tcp" | "udp"])[];
|
||||
redirections?: ContainerConfigRedirection[];
|
||||
cmd_opts?: Deno.CommandOptions;
|
||||
syscall_filter?: string[];
|
||||
}) {
|
||||
|
@ -17,8 +18,12 @@ export function container_command(name: string, directory: string, opts?: {
|
|||
];
|
||||
if (opts?.veth ?? false) args.push("--network-veth");
|
||||
if (opts?.boot ?? false) args.push("--boot");
|
||||
for (const [from, to, proto] of opts?.ports ?? []) {
|
||||
args.push(proto === undefined ? `--port=${from}:${to}` : `--port=${proto}:${from}:${to}`);
|
||||
for (const redir of opts?.redirections ?? []) {
|
||||
if (redir.kind === "http") args.push(`--port=${redir.port}`);
|
||||
if (redir.kind === "port") {
|
||||
args.push(`--port=tcp:${redir.from}:${redir.to}`);
|
||||
args.push(`--port=udp:${redir.from}:${redir.to}`);
|
||||
}
|
||||
}
|
||||
for (const call of opts?.syscall_filter ?? []) args.push(`--system-call-filter=${call}`);
|
||||
const command = new Deno.Command("systemd-nspawn", { ...opts?.cmd_opts, args });
|
||||
|
|
|
@ -93,3 +93,9 @@ export function log_from(...prefixes: string[]) {
|
|||
console.log(prefix, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
export async function async_collect<T>(gen: AsyncIterable<T>) {
|
||||
const result = [] as T[];
|
||||
for await (const item of gen) result.push(item);
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue