Compare commits
20 Commits
8651f60645
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
52b4c9000f
|
|||
|
cf0be21596
|
|||
|
7a7275cf66
|
|||
|
466449b7b8
|
|||
|
fb44bc2178
|
|||
|
1a46cf7ef3
|
|||
|
8886b23434
|
|||
|
1fd741861e
|
|||
|
2726baa6bd
|
|||
|
36427a41a4
|
|||
|
d1df4ff6a2
|
|||
|
fb22cc7528
|
|||
|
226aba437a
|
|||
|
7fa635170a
|
|||
|
2af0136703
|
|||
|
1fde73778b
|
|||
|
92496c8b8e
|
|||
| 80e32a7887 | |||
|
16f60f6075
|
|||
|
c63eeb83a0
|
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
FROM archlinux:base-devel AS builder
|
||||||
|
|
||||||
|
RUN pacman -Syu npm lua luarocks just --noconfirm
|
||||||
|
|
||||||
|
# build frontend
|
||||||
|
WORKDIR /frontend
|
||||||
|
COPY frontend .
|
||||||
|
RUN npm install && npm run build
|
||||||
|
|
||||||
|
# build lua
|
||||||
|
WORKDIR /lua
|
||||||
|
COPY lua .
|
||||||
|
RUN luarocks install tl && \
|
||||||
|
luarocks install dumbluaparser && \
|
||||||
|
eval $(luarocks path) && \
|
||||||
|
just build
|
||||||
|
|
||||||
|
# build final container
|
||||||
|
FROM python:3
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
COPY server .
|
||||||
|
COPY --from=builder /frontend/dist frontend
|
||||||
|
COPY --from=builder /lua/out lua
|
||||||
|
|
||||||
|
RUN pip install -e "."
|
||||||
|
|
||||||
|
ENV UVICORN_HOST="0.0.0.0"
|
||||||
|
ENV UVICORN_PORT="80"
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["uvicorn", "server:app"]
|
||||||
1
db/.gitignore
vendored
Normal file
1
db/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
secret.env
|
||||||
19
db/docker-compose.yml
Normal file
19
db/docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Use root/example as user/password credentials
|
||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mongo:
|
||||||
|
image: mongo
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 27017:27017
|
||||||
|
env_file:
|
||||||
|
- secret.env
|
||||||
|
|
||||||
|
mongo-express:
|
||||||
|
image: mongo-express
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 8081:8081
|
||||||
|
env_file:
|
||||||
|
- secret.env
|
||||||
5
db/secret.env.example
Normal file
5
db/secret.env.example
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
MONGO_INITDB_ROOT_USERNAME="user"
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD="pass"
|
||||||
|
ME_CONFIG_MONGODB_ADMINUSERNAME="user"
|
||||||
|
ME_CONFIG_MONGODB_ADMINPASSWORD="pass"
|
||||||
|
ME_CONFIG_MONGODB_URL="mongodb://user:pass@mongo:27017/"
|
||||||
568
frontend/package-lock.json
generated
568
frontend/package-lock.json
generated
@@ -11,7 +11,9 @@
|
|||||||
"@fortawesome/fontawesome-free": "^6.2.0",
|
"@fortawesome/fontawesome-free": "^6.2.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.1",
|
"@sveltejs/vite-plugin-svelte": "^1.0.1",
|
||||||
"@tsconfig/svelte": "^3.0.0",
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
|
"@types/ol": "^6.5.3",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
|
"ol": "^7.1.0",
|
||||||
"sass": "^1.53.0",
|
"sass": "^1.53.0",
|
||||||
"svelte": "^3.49.0",
|
"svelte": "^3.49.0",
|
||||||
"svelte-check": "^2.8.0",
|
"svelte-check": "^2.8.0",
|
||||||
@@ -73,6 +75,49 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mapbox/jsonlint-lines-primitives": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@mapbox/mapbox-gl-style-spec": {
|
||||||
|
"version": "13.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.26.0.tgz",
|
||||||
|
"integrity": "sha512-Ya1WiNz1qYau7xPYPQUbionrw9pjgZAIebGQdDXgwJuSAWeVCr02P7rqbYFHbXqX5TeAaq4qVpcaJb9oZtgaVQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@mapbox/jsonlint-lines-primitives": "~2.0.2",
|
||||||
|
"@mapbox/point-geometry": "^0.1.0",
|
||||||
|
"@mapbox/unitbezier": "^0.0.0",
|
||||||
|
"csscolorparser": "~1.0.2",
|
||||||
|
"json-stringify-pretty-compact": "^2.0.0",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"rw": "^1.3.3",
|
||||||
|
"sort-object": "^0.3.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"gl-style-composite": "bin/gl-style-composite.js",
|
||||||
|
"gl-style-format": "bin/gl-style-format.js",
|
||||||
|
"gl-style-migrate": "bin/gl-style-migrate.js",
|
||||||
|
"gl-style-validate": "bin/gl-style-validate.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@mapbox/point-geometry": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@mapbox/unitbezier": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -108,6 +153,12 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@petamoriken/float16": {
|
||||||
|
"version": "3.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.6.6.tgz",
|
||||||
|
"integrity": "sha512-3MUulwMtsdCA9lw8a/Kc0XDBJJVCkYTQ5aGd+///TbfkOMXoOGAzzoiYKwPEsLYZv7He7fKJ/mCacqKOO7REyg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@rollup/pluginutils": {
|
"node_modules/@rollup/pluginutils": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
||||||
@@ -154,18 +205,48 @@
|
|||||||
"integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==",
|
"integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/arcgis-rest-api": {
|
||||||
|
"version": "10.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/arcgis-rest-api/-/arcgis-rest-api-10.4.5.tgz",
|
||||||
|
"integrity": "sha512-MhpTj3aaURIFhK6pBRF50yCHW5TpbeuC1E81juovfNesSOshsQnCzludhpBhIr2pNzplTBlfzrT7RKiLZ5F3Tw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/geojson": {
|
||||||
|
"version": "7946.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
|
||||||
|
"integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "18.7.14",
|
"version": "18.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
|
||||||
"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==",
|
"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ol": {
|
||||||
|
"version": "6.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ol/-/ol-6.5.3.tgz",
|
||||||
|
"integrity": "sha512-C0Sm5dytTfRxztYFMuWq0IBJYfMffPF4GzXI/s4ZyJlNZ8AAdS+9fW0iGOyYkTb3ZQmfYWYdAzMqwGXfHVw+3A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/arcgis-rest-api": "*",
|
||||||
|
"@types/geojson": "*",
|
||||||
|
"@types/rbush": "*",
|
||||||
|
"@types/topojson-specification": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/pug": {
|
"node_modules/@types/pug": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
|
||||||
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/rbush": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-W3ue/GYWXBOpkRm0VSoifrP3HV0Ni47aVJWvXyWMcbtpBy/l/K/smBRiJ+fI8f7shXRjZBiux+iJzYbh7VmcZg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/sass": {
|
"node_modules/@types/sass": {
|
||||||
"version": "1.43.1",
|
"version": "1.43.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz",
|
||||||
@@ -175,6 +256,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/topojson-specification": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-SGc1NdX9g3UGDp6S+p+uyG+Z8CehS51sUJ9bejA25Xgn2kkAguILk6J9nxXK+0M/mbTBN7ypMA7+4HVLNMJ8ag==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/anymatch": {
|
"node_modules/anymatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
@@ -282,6 +372,12 @@
|
|||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/csscolorparser": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
@@ -323,6 +419,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/earcut": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/es6-promise": {
|
"node_modules/es6-promise": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||||
@@ -754,6 +856,25 @@
|
|||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/geotiff": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-aG8h9bJccGusioPsEWsEqx8qdXpZN71A20WCvRKGxcnHSOWLKmC5ZmsAmodfxb9TRQvs+89KikGuPzxchhA+Uw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@petamoriken/float16": "^3.4.7",
|
||||||
|
"lerc": "^3.0.0",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"pako": "^2.0.4",
|
||||||
|
"parse-headers": "^2.0.2",
|
||||||
|
"web-worker": "^1.2.0",
|
||||||
|
"xml-utils": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"browsers": "defaults",
|
||||||
|
"node": ">=10.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||||
@@ -804,6 +925,26 @@
|
|||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/immutable": {
|
"node_modules/immutable": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
|
||||||
@@ -896,6 +1037,12 @@
|
|||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/json-stringify-pretty-compact": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
@@ -905,6 +1052,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lerc": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/lower-case": {
|
"node_modules/lower-case": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||||
@@ -914,6 +1067,18 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.26.3",
|
"version": "0.26.3",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
|
||||||
@@ -926,6 +1091,12 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mapbox-to-css-font": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-QQ/iKiM43DM9+aujTL45Iz5o7gDeSFmy4LPl3HZmNcwCE++NxGazf+yFpY+wCb+YS23sDa1ghpo3zrNFOcHlow==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@@ -1033,6 +1204,33 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ol": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ol/-/ol-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-mAeV5Ca4mFhYaJoGWNZnIMN5VNnFTf63FgZjBiYu/DjQDGKNsD5QyvvqVziioVdOOgl6b8rPB/ypj2XNBinPwA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"earcut": "^2.2.3",
|
||||||
|
"geotiff": "2.0.4",
|
||||||
|
"ol-mapbox-style": "9.1.0",
|
||||||
|
"pbf": "3.2.1",
|
||||||
|
"rbush": "^3.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/openlayers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ol-mapbox-style": {
|
||||||
|
"version": "9.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-9.1.0.tgz",
|
||||||
|
"integrity": "sha512-R/XE6FdviaXNdnSw6ItHSEreMtQU68cwQCGv4Kl8yG0V1dZhnI5JWr8IOphJwffPVxfWTCnJb5aALGSB89MvhA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@mapbox/mapbox-gl-style-spec": "^13.23.1",
|
||||||
|
"mapbox-to-css-font": "^2.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
@@ -1042,6 +1240,12 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pako": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -1054,6 +1258,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parse-headers": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/pascal-case": {
|
"node_modules/pascal-case": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
||||||
@@ -1079,6 +1289,19 @@
|
|||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/pbf": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ieee754": "^1.1.12",
|
||||||
|
"resolve-protobuf-schema": "^2.1.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"pbf": "bin/pbf"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
@@ -1121,6 +1344,12 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/protocol-buffers-schema": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/queue-microtask": {
|
"node_modules/queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
@@ -1141,6 +1370,21 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/quickselect": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/rbush": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"quickselect": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
@@ -1179,6 +1423,15 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/resolve-protobuf-schema": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"protocol-buffers-schema": "^3.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reusify": {
|
"node_modules/reusify": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
@@ -1239,6 +1492,12 @@
|
|||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rw": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/sade": {
|
"node_modules/sade": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
|
||||||
@@ -1295,6 +1554,37 @@
|
|||||||
"sorcery": "bin/index.js"
|
"sorcery": "bin/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sort-asc": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-jBgdDd+rQ+HkZF2/OHCmace5dvpos/aWQpcxuyRs9QUbPRnkEJmYVo81PIGpjIdpOcsnJ4rGjStfDHsbn+UVyw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sort-desc": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz",
|
||||||
|
"integrity": "sha512-jfZacW5SKOP97BF5rX5kQfJmRVZP5/adDUTY8fCSPvNcXDVpUEe2pr/iKGlcyZzchRJZrswnp68fgk3qBXgkJw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sort-object": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-aAQiEdqFTTdsvUFxXm3umdo04J7MRljoVGbBlkH7BgNsMvVNAJyGj7C/wV1A8wHWAJj/YikeZbfuCKqhggNWGA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"sort-asc": "^0.1.0",
|
||||||
|
"sort-desc": "^0.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
@@ -1551,11 +1841,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-worker": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/xml-utils": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-z4unVPZruEDC3tfyd7wvWfjclnMz34iwQpv8H28H+qREpjKkR083MBvcrWXfJrIcrSmHR5ghguOcgQqWdnBpVA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1594,6 +1902,40 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@mapbox/jsonlint-lines-primitives": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@mapbox/mapbox-gl-style-spec": {
|
||||||
|
"version": "13.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.26.0.tgz",
|
||||||
|
"integrity": "sha512-Ya1WiNz1qYau7xPYPQUbionrw9pjgZAIebGQdDXgwJuSAWeVCr02P7rqbYFHbXqX5TeAaq4qVpcaJb9oZtgaVQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@mapbox/jsonlint-lines-primitives": "~2.0.2",
|
||||||
|
"@mapbox/point-geometry": "^0.1.0",
|
||||||
|
"@mapbox/unitbezier": "^0.0.0",
|
||||||
|
"csscolorparser": "~1.0.2",
|
||||||
|
"json-stringify-pretty-compact": "^2.0.0",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"rw": "^1.3.3",
|
||||||
|
"sort-object": "^0.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@mapbox/point-geometry": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@mapbox/unitbezier": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -1620,6 +1962,12 @@
|
|||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@petamoriken/float16": {
|
||||||
|
"version": "3.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.6.6.tgz",
|
||||||
|
"integrity": "sha512-3MUulwMtsdCA9lw8a/Kc0XDBJJVCkYTQ5aGd+///TbfkOMXoOGAzzoiYKwPEsLYZv7He7fKJ/mCacqKOO7REyg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@rollup/pluginutils": {
|
"@rollup/pluginutils": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
||||||
@@ -1650,18 +1998,48 @@
|
|||||||
"integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==",
|
"integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/arcgis-rest-api": {
|
||||||
|
"version": "10.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/arcgis-rest-api/-/arcgis-rest-api-10.4.5.tgz",
|
||||||
|
"integrity": "sha512-MhpTj3aaURIFhK6pBRF50yCHW5TpbeuC1E81juovfNesSOshsQnCzludhpBhIr2pNzplTBlfzrT7RKiLZ5F3Tw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/geojson": {
|
||||||
|
"version": "7946.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
|
||||||
|
"integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "18.7.14",
|
"version": "18.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
|
||||||
"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==",
|
"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/ol": {
|
||||||
|
"version": "6.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ol/-/ol-6.5.3.tgz",
|
||||||
|
"integrity": "sha512-C0Sm5dytTfRxztYFMuWq0IBJYfMffPF4GzXI/s4ZyJlNZ8AAdS+9fW0iGOyYkTb3ZQmfYWYdAzMqwGXfHVw+3A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/arcgis-rest-api": "*",
|
||||||
|
"@types/geojson": "*",
|
||||||
|
"@types/rbush": "*",
|
||||||
|
"@types/topojson-specification": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/pug": {
|
"@types/pug": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
|
||||||
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/rbush": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-W3ue/GYWXBOpkRm0VSoifrP3HV0Ni47aVJWvXyWMcbtpBy/l/K/smBRiJ+fI8f7shXRjZBiux+iJzYbh7VmcZg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/sass": {
|
"@types/sass": {
|
||||||
"version": "1.43.1",
|
"version": "1.43.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz",
|
||||||
@@ -1671,6 +2049,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/topojson-specification": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-SGc1NdX9g3UGDp6S+p+uyG+Z8CehS51sUJ9bejA25Xgn2kkAguILk6J9nxXK+0M/mbTBN7ypMA7+4HVLNMJ8ag==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"anymatch": {
|
"anymatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
@@ -1752,6 +2139,12 @@
|
|||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"csscolorparser": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
@@ -1779,6 +2172,12 @@
|
|||||||
"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
|
"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"earcut": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"es6-promise": {
|
"es6-promise": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||||
@@ -2010,6 +2409,21 @@
|
|||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"geotiff": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-aG8h9bJccGusioPsEWsEqx8qdXpZN71A20WCvRKGxcnHSOWLKmC5ZmsAmodfxb9TRQvs+89KikGuPzxchhA+Uw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@petamoriken/float16": "^3.4.7",
|
||||||
|
"lerc": "^3.0.0",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"pako": "^2.0.4",
|
||||||
|
"parse-headers": "^2.0.2",
|
||||||
|
"web-worker": "^1.2.0",
|
||||||
|
"xml-utils": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||||
@@ -2048,6 +2462,12 @@
|
|||||||
"function-bind": "^1.1.1"
|
"function-bind": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"immutable": {
|
"immutable": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz",
|
||||||
@@ -2119,12 +2539,24 @@
|
|||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"json-stringify-pretty-compact": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"kleur": {
|
"kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
|
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lerc": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"lower-case": {
|
"lower-case": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||||
@@ -2134,6 +2566,15 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.26.3",
|
"version": "0.26.3",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
|
||||||
@@ -2143,6 +2584,12 @@
|
|||||||
"sourcemap-codec": "^1.4.8"
|
"sourcemap-codec": "^1.4.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mapbox-to-css-font": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-QQ/iKiM43DM9+aujTL45Iz5o7gDeSFmy4LPl3HZmNcwCE++NxGazf+yFpY+wCb+YS23sDa1ghpo3zrNFOcHlow==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"merge2": {
|
"merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@@ -2223,6 +2670,29 @@
|
|||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ol": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ol/-/ol-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-mAeV5Ca4mFhYaJoGWNZnIMN5VNnFTf63FgZjBiYu/DjQDGKNsD5QyvvqVziioVdOOgl6b8rPB/ypj2XNBinPwA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"earcut": "^2.2.3",
|
||||||
|
"geotiff": "2.0.4",
|
||||||
|
"ol-mapbox-style": "9.1.0",
|
||||||
|
"pbf": "3.2.1",
|
||||||
|
"rbush": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ol-mapbox-style": {
|
||||||
|
"version": "9.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-9.1.0.tgz",
|
||||||
|
"integrity": "sha512-R/XE6FdviaXNdnSw6ItHSEreMtQU68cwQCGv4Kl8yG0V1dZhnI5JWr8IOphJwffPVxfWTCnJb5aALGSB89MvhA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@mapbox/mapbox-gl-style-spec": "^13.23.1",
|
||||||
|
"mapbox-to-css-font": "^2.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
@@ -2232,6 +2702,12 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pako": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"parent-module": {
|
"parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -2241,6 +2717,12 @@
|
|||||||
"callsites": "^3.0.0"
|
"callsites": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"parse-headers": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"pascal-case": {
|
"pascal-case": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
||||||
@@ -2263,6 +2745,16 @@
|
|||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pbf": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ieee754": "^1.1.12",
|
||||||
|
"resolve-protobuf-schema": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"picocolors": {
|
"picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
@@ -2286,12 +2778,33 @@
|
|||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"protocol-buffers-schema": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"queue-microtask": {
|
"queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"quickselect": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"rbush": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"quickselect": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
@@ -2318,6 +2831,15 @@
|
|||||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"resolve-protobuf-schema": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"protocol-buffers-schema": "^3.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"reusify": {
|
"reusify": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
@@ -2351,6 +2873,12 @@
|
|||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rw": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"sade": {
|
"sade": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
|
||||||
@@ -2395,6 +2923,28 @@
|
|||||||
"sourcemap-codec": "^1.3.0"
|
"sourcemap-codec": "^1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort-asc": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-jBgdDd+rQ+HkZF2/OHCmace5dvpos/aWQpcxuyRs9QUbPRnkEJmYVo81PIGpjIdpOcsnJ4rGjStfDHsbn+UVyw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"sort-desc": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz",
|
||||||
|
"integrity": "sha512-jfZacW5SKOP97BF5rX5kQfJmRVZP5/adDUTY8fCSPvNcXDVpUEe2pr/iKGlcyZzchRJZrswnp68fgk3qBXgkJw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"sort-object": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-aAQiEdqFTTdsvUFxXm3umdo04J7MRljoVGbBlkH7BgNsMvVNAJyGj7C/wV1A8wHWAJj/YikeZbfuCKqhggNWGA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"sort-asc": "^0.1.0",
|
||||||
|
"sort-desc": "^0.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map-js": {
|
"source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
@@ -2529,11 +3079,29 @@
|
|||||||
"rollup": ">=2.75.6 <2.77.0 || ~2.77.0"
|
"rollup": ">=2.75.6 <2.77.0 || ~2.77.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"web-worker": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"xml-utils": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-z4unVPZruEDC3tfyd7wvWfjclnMz34iwQpv8H28H+qREpjKkR083MBvcrWXfJrIcrSmHR5ghguOcgQqWdnBpVA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
"@fortawesome/fontawesome-free": "^6.2.0",
|
"@fortawesome/fontawesome-free": "^6.2.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.1",
|
"@sveltejs/vite-plugin-svelte": "^1.0.1",
|
||||||
"@tsconfig/svelte": "^3.0.0",
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
|
"@types/ol": "^6.5.3",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
|
"ol": "^7.1.0",
|
||||||
"sass": "^1.53.0",
|
"sass": "^1.53.0",
|
||||||
"svelte": "^3.49.0",
|
"svelte": "^3.49.0",
|
||||||
"svelte-check": "^2.8.0",
|
"svelte-check": "^2.8.0",
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
import { user } from "./stores";
|
import { user } from "./stores";
|
||||||
|
|
||||||
import Navbar from "./Navbar.svelte";
|
import P404 from "./pages/P404.svelte";
|
||||||
|
import Mining from "./pages/mining/Mining.svelte";
|
||||||
|
import BaseLayout from "./BaseLayout.svelte";
|
||||||
|
import Monitoring from "./pages/monitoring/Monitoring.svelte";
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const res = await fetch("/user/me");
|
const res = await fetch("/user/me");
|
||||||
@@ -13,53 +16,27 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Router>
|
<Router>
|
||||||
<Navbar />
|
<Route path="/">
|
||||||
|
<BaseLayout>
|
||||||
<div class="is-flex-grow-1">
|
|
||||||
<Route path="/">
|
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<p>Hallo i bims 1 frontend</p>
|
<p>Hallo i bims 1 frontend</p>
|
||||||
</section>
|
</section>
|
||||||
</Route>
|
</BaseLayout>
|
||||||
|
</Route>
|
||||||
|
|
||||||
<Route path="/foo">
|
<Route path="monitoring/*">
|
||||||
<section class="hero is-danger is-fullheight">
|
<BaseLayout><Monitoring /></BaseLayout>
|
||||||
<div class="hero-body">
|
</Route>
|
||||||
<div class="">
|
|
||||||
<p class="title">Fullheight hero</p>
|
|
||||||
<p class="subtitle">Fullheight subtitle</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
<Route path="/bar">bar</Route>
|
<Route path="mining">
|
||||||
|
<Mining />
|
||||||
|
</Route>
|
||||||
|
|
||||||
<Route path="/monitoring">monitoring</Route>
|
<Route path="stats">
|
||||||
|
<BaseLayout>stats</BaseLayout>
|
||||||
|
</Route>
|
||||||
|
|
||||||
<Route path="/mining">mining</Route>
|
<Route>
|
||||||
|
<BaseLayout><P404 /></BaseLayout>
|
||||||
<Route path="/stats">stats</Route>
|
</Route>
|
||||||
|
|
||||||
<Route>
|
|
||||||
<section class="section">
|
|
||||||
<div class="container has-text-centered">
|
|
||||||
<h1 class="title is-1">404</h1>
|
|
||||||
<h2 class="subtitle is-5">
|
|
||||||
The page you are trying to reach either
|
|
||||||
<strong>does not exist</strong>
|
|
||||||
or
|
|
||||||
<strong>you are not authorized</strong>
|
|
||||||
to view it.
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</Route>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="has-text-centered">
|
|
||||||
Test footer please ignore
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
20
frontend/src/BaseLayout.svelte
Normal file
20
frontend/src/BaseLayout.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Footer from "./Footer.svelte";
|
||||||
|
import Navbar from "./Navbar.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="main-container">
|
||||||
|
<Navbar />
|
||||||
|
<div class="is-flex-grow-1">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.main-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
13
frontend/src/Footer.svelte
Normal file
13
frontend/src/Footer.svelte
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { useLocation } from "svelte-navigator";
|
||||||
|
const location = useLocation();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $location.pathname !== "/mining"}
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="has-text-centered">
|
||||||
|
<p>Test footer please ignore</p>
|
||||||
|
<p>location: {$location.pathname}</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
{/if}
|
||||||
@@ -30,8 +30,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="navbar-menu {menu_open ? 'is-active' : ''}">
|
<div class="navbar-menu {menu_open ? 'is-active' : ''}">
|
||||||
<div class="navbar-start">
|
<div class="navbar-start">
|
||||||
<Navlink target="/foo" text="Foo" icon="fas fa-hippo" />
|
|
||||||
<Navlink target="/bar" text="Bar" icon="fas fa-otter" />
|
|
||||||
<Navlink target="/monitoring" text="Monitoring" icon="fas fa-binoculars" />
|
<Navlink target="/monitoring" text="Monitoring" icon="fas fa-binoculars" />
|
||||||
<Navlink target="/mining" text="Mining" icon="fas fa-person-digging" />
|
<Navlink target="/mining" text="Mining" icon="fas fa-person-digging" />
|
||||||
<Navlink target="/stats" text="Statistics" icon="fas fa-chart-line" />
|
<Navlink target="/stats" text="Statistics" icon="fas fa-chart-line" />
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<Link
|
<Link
|
||||||
to={target}
|
to={target}
|
||||||
class="navbar-item is-tab {$location.pathname === target
|
class="navbar-item is-tab {$location.pathname.startsWith(target)
|
||||||
? 'is-active'
|
? 'is-active'
|
||||||
: ''}"
|
: ''}"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts";
|
|||||||
@import "@fortawesome/fontawesome-free/scss/brands.scss";
|
@import "@fortawesome/fontawesome-free/scss/brands.scss";
|
||||||
@import "@fortawesome/fontawesome-free/scss/v4-shims.scss";
|
@import "@fortawesome/fontawesome-free/scss/v4-shims.scss";
|
||||||
|
|
||||||
body {
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/mefechoel/svelte-navigator#what-are-the-weird-rectangles-around-the-headings-in-my-app
|
// https://github.com/mefechoel/svelte-navigator#what-are-the-weird-rectangles-around-the-headings-in-my-app
|
||||||
h1:focus {
|
h1:focus,
|
||||||
|
h2:focus,
|
||||||
|
h3:focus,
|
||||||
|
h4:focus,
|
||||||
|
h5:focus,
|
||||||
|
h6:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import 'vite/modulepreload-polyfill'
|
import 'vite/modulepreload-polyfill'
|
||||||
|
|
||||||
|
import "ol/ol.css";
|
||||||
import "./app.scss";
|
import "./app.scss";
|
||||||
|
|
||||||
import App from "./App.svelte";
|
import App from "./App.svelte";
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
|
|||||||
12
frontend/src/pages/P404.svelte
Normal file
12
frontend/src/pages/P404.svelte
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<section class="section">
|
||||||
|
<div class="container has-text-centered">
|
||||||
|
<h1 class="title is-1">404</h1>
|
||||||
|
<h2 class="subtitle is-5">
|
||||||
|
The page you are trying to reach either
|
||||||
|
<strong>does not exist</strong>
|
||||||
|
or
|
||||||
|
<strong>you are not authorized</strong>
|
||||||
|
to view it.
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
78
frontend/src/pages/mining/Mining.svelte
Normal file
78
frontend/src/pages/mining/Mining.svelte
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Navbar from "../../Navbar.svelte";
|
||||||
|
|
||||||
|
import {
|
||||||
|
ol_proxy,
|
||||||
|
type Unmined,
|
||||||
|
type UnminedOptions,
|
||||||
|
type UnminedRegions,
|
||||||
|
} from "./unmined";
|
||||||
|
|
||||||
|
let unmined: Unmined;
|
||||||
|
|
||||||
|
export let id = "map";
|
||||||
|
|
||||||
|
type Metadata = {
|
||||||
|
properties: UnminedOptions;
|
||||||
|
regions: UnminedRegions;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function get_unmined() {
|
||||||
|
if (unmined === undefined) {
|
||||||
|
let resp = await fetch("map/unmined.js");
|
||||||
|
let code = await resp.text();
|
||||||
|
unmined = Function("ol", code).call({}, ol_proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
let resp = await fetch("map/metadata.js");
|
||||||
|
let code = await resp.text();
|
||||||
|
let meta: Metadata = Function(code).call({}); // TODO possibly vulnerable to prototype pollution
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupMap(node: HTMLDivElement, metadata: Metadata) {
|
||||||
|
unmined.map(node.id, metadata.properties, metadata.regions);
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
if (unmined.openlayersMap) {
|
||||||
|
unmined.openlayersMap.setTarget(null);
|
||||||
|
unmined.openlayersMap = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="map-outer">
|
||||||
|
<Navbar />
|
||||||
|
{#await get_unmined() then metadata}
|
||||||
|
<div class="map-target" {id} use:setupMap={metadata} />
|
||||||
|
{:catch err}
|
||||||
|
<div class="container">
|
||||||
|
<article class="message is-danger mt-5">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>Error loading map</p>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">
|
||||||
|
<p>Something went wrong:</p>
|
||||||
|
<figure>
|
||||||
|
<pre>{err}</pre>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
{/await}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.map-outer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
.map-target {
|
||||||
|
flex-grow: 1;
|
||||||
|
background-color: #e2e2e2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
71
frontend/src/pages/mining/unmined.ts
Normal file
71
frontend/src/pages/mining/unmined.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import type OlMap from "ol/Map";
|
||||||
|
import type VectorLayer from "ol/layer/Vector";
|
||||||
|
import type VectorSource from "ol/source/Vector";
|
||||||
|
import { boundingExtent } from "ol/extent";
|
||||||
|
import { addCoordinateTransforms, Projection } from "ol/proj";
|
||||||
|
import TileGrid from "ol/tilegrid/TileGrid";
|
||||||
|
import XYZ from "ol/source/XYZ";
|
||||||
|
import Tile from "ol/layer/Tile";
|
||||||
|
import { createStringXY } from "ol/coordinate";
|
||||||
|
import MousePosition from "ol/control/MousePosition";
|
||||||
|
import { defaults } from "ol/control/defaults";
|
||||||
|
import { Map, View } from "ol";
|
||||||
|
import SourceVector from "ol/source/Vector";
|
||||||
|
import LayerVector from "ol/layer/Vector";
|
||||||
|
|
||||||
|
export type UnminedOptions = {
|
||||||
|
minZoom: number;
|
||||||
|
maxZoom: number;
|
||||||
|
defaultZoom: number;
|
||||||
|
imageFormat: string;
|
||||||
|
minRegionX: number;
|
||||||
|
minRegionZ: number;
|
||||||
|
maxRegionX: number;
|
||||||
|
maxRegionZ: number;
|
||||||
|
worldName: string;
|
||||||
|
background: string;
|
||||||
|
markers: Array<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UnminedRegions = {
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
m: Uint32Array,
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export type Unmined = {
|
||||||
|
openlayersMap: OlMap,
|
||||||
|
map: (mapId: string, options: UnminedOptions, regions: UnminedRegions) => void,
|
||||||
|
createMarkersLayer: (markers, dataProjection, viewProjection) => VectorLayer<VectorSource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** (cursed) proxy variable to provide the fetched unmined script access to `ol.extent.boundingExtent` etc */
|
||||||
|
export const ol_proxy = {
|
||||||
|
extent: {
|
||||||
|
boundingExtent: boundingExtent,
|
||||||
|
},
|
||||||
|
proj: {
|
||||||
|
Projection: Projection,
|
||||||
|
addCoordinateTransforms: addCoordinateTransforms,
|
||||||
|
},
|
||||||
|
tilegrid: {
|
||||||
|
TileGrid: TileGrid,
|
||||||
|
},
|
||||||
|
layer: {
|
||||||
|
Tile: Tile,
|
||||||
|
Vector: LayerVector,
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
XYZ: XYZ,
|
||||||
|
Vector: SourceVector,
|
||||||
|
},
|
||||||
|
control: {
|
||||||
|
MousePosition: MousePosition,
|
||||||
|
defaults: defaults,
|
||||||
|
},
|
||||||
|
coordinate: {
|
||||||
|
createStringXY: createStringXY,
|
||||||
|
},
|
||||||
|
View: View,
|
||||||
|
Map: Map,
|
||||||
|
};
|
||||||
94
frontend/src/pages/monitoring/Event.svelte
Normal file
94
frontend/src/pages/monitoring/Event.svelte
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
type Event = {
|
||||||
|
icon: string;
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
const mappings: Map<string, (any) => Event> = new Map([
|
||||||
|
[
|
||||||
|
"computer_connect",
|
||||||
|
(value) => ({
|
||||||
|
icon: "fas fa-circle-plus",
|
||||||
|
text: `Computer ${value.computer_id} connected`,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"computer_disconnect",
|
||||||
|
(value) => ({
|
||||||
|
icon: "fas fa-circle-minus",
|
||||||
|
text: `Computer ${value.computer_id} disconnected`,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export let timestamp: string;
|
||||||
|
export let type: string;
|
||||||
|
export let value: any;
|
||||||
|
|
||||||
|
let icon = "far fa-circle-question";
|
||||||
|
let text = `Unknown event (${type})`;
|
||||||
|
|
||||||
|
let m = mappings.get(type);
|
||||||
|
if (m) {
|
||||||
|
let mapped = m(value);
|
||||||
|
icon = mapped.icon;
|
||||||
|
text = mapped.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
let datetime = new Date(timestamp);
|
||||||
|
|
||||||
|
let expanded = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="entry"
|
||||||
|
on:click={() => {
|
||||||
|
expanded = !expanded;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="headers">
|
||||||
|
<div><span class="icon"><i class={icon} /></span></div>
|
||||||
|
<div class="header-title">{text}</div>
|
||||||
|
<div>{datetime}</div>
|
||||||
|
<div>
|
||||||
|
<span class="icon"
|
||||||
|
><i
|
||||||
|
class="fas {expanded ? 'fa-angle-up' : 'fa-angle-down'}"
|
||||||
|
/></span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if expanded}
|
||||||
|
<div class="expandable">
|
||||||
|
<pre>{JSON.stringify(value, null, 1)}</pre>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.entry {
|
||||||
|
background-color: #fafafa;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
border-top: 1px solid #dbdbdb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headers {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
flex: 1 1 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
35
frontend/src/pages/monitoring/Events.svelte
Normal file
35
frontend/src/pages/monitoring/Events.svelte
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import Event from "./Event.svelte";
|
||||||
|
|
||||||
|
const ENDPOINT = "/api/events";
|
||||||
|
|
||||||
|
let events: { _id: string; timestamp: string; type: string; value: any }[] =
|
||||||
|
[];
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
let int = setInterval(async () => {
|
||||||
|
let r = await fetch(ENDPOINT);
|
||||||
|
events = await r.json();
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(int);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="events">
|
||||||
|
{#each events as event (event._id)}
|
||||||
|
<Event {...event} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.events {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
28
frontend/src/pages/monitoring/Monitoring.svelte
Normal file
28
frontend/src/pages/monitoring/Monitoring.svelte
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Link, Route, useParams } from "svelte-navigator";
|
||||||
|
import Events from "./Events.svelte";
|
||||||
|
import Viewer from "./Viewer.svelte";
|
||||||
|
|
||||||
|
const uuids = ["8b9faf9f-9470-4a50-b405-0af5f0152550"];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<Route path="/">
|
||||||
|
<p>Yo wassup</p>
|
||||||
|
<ul>
|
||||||
|
{#each uuids as id}
|
||||||
|
<li><Link to="./{id}">{id}</Link></li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
<p>eventeroni</p>
|
||||||
|
<Events />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Route path=":id" let:params>
|
||||||
|
<h1 class="title">ASSUMING DIRECT CONTROL</h1>
|
||||||
|
<Viewer uuid={params.id} />
|
||||||
|
<Link to="..">fuck go back</Link>
|
||||||
|
</Route>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
121
frontend/src/pages/monitoring/Screen.svelte
Normal file
121
frontend/src/pages/monitoring/Screen.svelte
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import termFont from "./term_font.png";
|
||||||
|
import { loadFont, charWidth, charHeight } from "./font";
|
||||||
|
import type { ScreenContent } from "./proto";
|
||||||
|
import { onDestroy, onMount } from "svelte";
|
||||||
|
|
||||||
|
export let content: ScreenContent;
|
||||||
|
|
||||||
|
let canvas: HTMLCanvasElement;
|
||||||
|
let composeCanvas: HTMLCanvasElement;
|
||||||
|
let font: ImageBitmap[];
|
||||||
|
|
||||||
|
const paddingX = 2,
|
||||||
|
paddingY = 2;
|
||||||
|
|
||||||
|
const toColor = (n: number) => `#${n.toString(16).padStart(6, "0")}`;
|
||||||
|
|
||||||
|
// SAFETY: Only called if all of (content, canvas, composeCanvas, font) are defined
|
||||||
|
function drawChar(
|
||||||
|
charCode: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
textColor: number,
|
||||||
|
backgroundColor: number
|
||||||
|
) {
|
||||||
|
let cx = canvas.getContext("2d");
|
||||||
|
let ccx = composeCanvas.getContext("2d");
|
||||||
|
|
||||||
|
const offsetX = paddingX + x * charWidth;
|
||||||
|
const offsetY = paddingY + y * charHeight;
|
||||||
|
|
||||||
|
let x0 = offsetX;
|
||||||
|
let y0 = offsetY;
|
||||||
|
let w = charWidth;
|
||||||
|
let h = charHeight;
|
||||||
|
|
||||||
|
// handle padding
|
||||||
|
if (x === 0) {
|
||||||
|
x0 -= paddingX;
|
||||||
|
w += paddingX;
|
||||||
|
} else if (x === content.width - 1) {
|
||||||
|
w += paddingX;
|
||||||
|
}
|
||||||
|
if (y === 0) {
|
||||||
|
y0 -= paddingY;
|
||||||
|
h += paddingY;
|
||||||
|
} else if (y === content.height - 1) {
|
||||||
|
h += paddingY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw background
|
||||||
|
cx.fillStyle = toColor(content.palette[backgroundColor]);
|
||||||
|
cx.fillRect(x0, y0, w, h);
|
||||||
|
|
||||||
|
// compose foreground
|
||||||
|
ccx.globalCompositeOperation = "source-over";
|
||||||
|
ccx.clearRect(0, 0, charWidth, charHeight);
|
||||||
|
|
||||||
|
ccx.fillStyle = toColor(content.palette[textColor]);
|
||||||
|
ccx.fillRect(0, 0, charWidth, charHeight);
|
||||||
|
ccx.globalCompositeOperation = "destination-in";
|
||||||
|
ccx.drawImage(font[charCode], 0, 0);
|
||||||
|
|
||||||
|
// draw foreground
|
||||||
|
cx.drawImage(composeCanvas, offsetX, offsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function redraw(content: ScreenContent) {
|
||||||
|
if (!canvas) return;
|
||||||
|
if (!font) return;
|
||||||
|
|
||||||
|
const cx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
cx.fillStyle = "#ff6600";
|
||||||
|
cx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.width = content.width * charWidth + 2 * paddingX;
|
||||||
|
canvas.height = content.height * charHeight + 2 * paddingY;
|
||||||
|
|
||||||
|
cx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
for (let y = 0; y < content.height; ++y) {
|
||||||
|
const line = content.text[y];
|
||||||
|
const fgLine = content.fg_color[y];
|
||||||
|
const bgLine = content.bg_color[y];
|
||||||
|
|
||||||
|
for (let x = 0; x < content.width; ++x) {
|
||||||
|
drawChar(
|
||||||
|
line.charCodeAt(x),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
parseInt(fgLine.charAt(x), 16),
|
||||||
|
parseInt(bgLine.charAt(x), 16)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: redraw(content);
|
||||||
|
|
||||||
|
const blinkInt = setInterval(() => {
|
||||||
|
|
||||||
|
}, 400);
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
font = await loadFont(termFont);
|
||||||
|
composeCanvas = document.createElement("canvas");
|
||||||
|
composeCanvas.width = charWidth;
|
||||||
|
composeCanvas.height = charHeight;
|
||||||
|
redraw(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
composeCanvas = null;
|
||||||
|
clearInterval(blinkInt);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<canvas bind:this={canvas} />
|
||||||
65
frontend/src/pages/monitoring/Viewer.svelte
Normal file
65
frontend/src/pages/monitoring/Viewer.svelte
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let uuid: string;
|
||||||
|
|
||||||
|
import { onDestroy, onMount } from "svelte";
|
||||||
|
import Screen from "./Screen.svelte";
|
||||||
|
|
||||||
|
const wsUrl = new URL(`/ipmi/browser/${uuid}/ws`, window.location.href);
|
||||||
|
wsUrl.protocol = wsUrl.protocol.replace("http", "ws");
|
||||||
|
|
||||||
|
const dummyData = {
|
||||||
|
x: -1,
|
||||||
|
y: -1,
|
||||||
|
width: 13,
|
||||||
|
height: 5,
|
||||||
|
blink: false,
|
||||||
|
fg: 0,
|
||||||
|
text: [
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" [NO SIGNAL] ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
],
|
||||||
|
fg_color: [
|
||||||
|
"0000000000000",
|
||||||
|
"0000000000000",
|
||||||
|
"0800000000080",
|
||||||
|
"0000000000000",
|
||||||
|
"0000000000000",
|
||||||
|
],
|
||||||
|
bg_color: [
|
||||||
|
"7777777777777",
|
||||||
|
"7777777777777",
|
||||||
|
"7777777777777",
|
||||||
|
"7777777777777",
|
||||||
|
"7777777777777",
|
||||||
|
],
|
||||||
|
palette: [
|
||||||
|
15790320, 15905331, 15040472, 10072818, 14605932, 8375321, 15905484,
|
||||||
|
5000268, 10066329, 5020082, 11691749, 3368652, 8349260, 5744206,
|
||||||
|
13388876, 1118481,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let socket: WebSocket | null = null;
|
||||||
|
let data;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
socket = new WebSocket(wsUrl);
|
||||||
|
|
||||||
|
socket.addEventListener("message", (event) => {
|
||||||
|
data = JSON.parse(event.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
console.log("onDestroy");
|
||||||
|
if (socket !== null) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Screen content={data || dummyData} />
|
||||||
|
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||||
25
frontend/src/pages/monitoring/font.ts
Normal file
25
frontend/src/pages/monitoring/font.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
export const charWidth = 6, charHeight = 9;
|
||||||
|
|
||||||
|
export async function loadFont(src: RequestInfo | URL): Promise<ImageBitmap[]> {
|
||||||
|
const fontImg = await fetch(src);
|
||||||
|
const fontBlob = await fontImg.blob();
|
||||||
|
|
||||||
|
async function getCharBitmap(x: number, y: number) {
|
||||||
|
const fontOffsetX = 1, fontOffsetY = 1, fontPaddingX = 2, fontPaddingY = 2;
|
||||||
|
|
||||||
|
const offsetX = (charWidth + fontPaddingX) * x + fontOffsetX;
|
||||||
|
const offsetY = (charHeight + fontPaddingY) * y + fontOffsetY;
|
||||||
|
|
||||||
|
return await createImageBitmap(fontBlob, offsetX, offsetY, charWidth, charHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
const font = Array(256);
|
||||||
|
|
||||||
|
for (let y = 0; y < 16; ++y) {
|
||||||
|
for (let x = 0; x < 16; ++x) {
|
||||||
|
const i = 16 * y + x;
|
||||||
|
font[i] = getCharBitmap(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return await Promise.all(font);
|
||||||
|
}
|
||||||
12
frontend/src/pages/monitoring/proto.ts
Normal file
12
frontend/src/pages/monitoring/proto.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export type ScreenContent = {
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
blink: boolean
|
||||||
|
fg: number
|
||||||
|
text: string[]
|
||||||
|
fg_color: string[]
|
||||||
|
bg_color: string[]
|
||||||
|
palette: number[]
|
||||||
|
}
|
||||||
BIN
frontend/src/pages/monitoring/term_font.png
Normal file
BIN
frontend/src/pages/monitoring/term_font.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
1
lua/.gitignore
vendored
Normal file
1
lua/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
out
|
||||||
20
lua/cc.d.tl
Normal file
20
lua/cc.d.tl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
global sleep: function(time: number)
|
||||||
|
|
||||||
|
global write: function(text: string): number
|
||||||
|
--global print: function(...: any): number
|
||||||
|
global printError: function(...: any)
|
||||||
|
|
||||||
|
--global type ReadCompletionFunction = function(partial: string): { string } | nil
|
||||||
|
--global read: function(replaceChar: string | nil, history: table | nil, completeFn: ReadCompletionFunction | nil, default: string | nil): string
|
||||||
|
|
||||||
|
global _HOST: string
|
||||||
|
global _CC_DEFAULT_SETTINGS: string
|
||||||
|
|
||||||
|
require("types/colors")
|
||||||
|
require("types/term")
|
||||||
|
require("types/parallel")
|
||||||
|
require("types/http")
|
||||||
|
require("types/shell")
|
||||||
|
require("types/window")
|
||||||
|
require("types/os")
|
||||||
|
|
||||||
32
lua/justfile
Normal file
32
lua/justfile
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
default:
|
||||||
|
@just --list
|
||||||
|
|
||||||
|
build: && manifest
|
||||||
|
tl build
|
||||||
|
@mkdir -p out/vendor
|
||||||
|
find src/vendor -name "*.lua" -exec cp -t out/vendor {} +
|
||||||
|
|
||||||
|
alias b := build
|
||||||
|
|
||||||
|
manifest_file := "out/manifest.txt"
|
||||||
|
manifest:
|
||||||
|
rm -f {{ manifest_file }}
|
||||||
|
find out -name "*.lua" -exec realpath --relative-to=out {} >> {{ manifest_file }} \;
|
||||||
|
|
||||||
|
min-build: build
|
||||||
|
find out -name "*.lua" -exec lua minify.lua {} \;
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r out
|
||||||
|
|
||||||
|
alias c := clean
|
||||||
|
|
||||||
|
watch_recipe := env_var_or_default("WATCH_RECIPE", "build")
|
||||||
|
|
||||||
|
watch:
|
||||||
|
while sleep 0.1; do \
|
||||||
|
find . -type f ! -path './out/*' | entr -d just {{ watch_recipe }}; \
|
||||||
|
[ $? -eq 0 ] && exit 0; \
|
||||||
|
done
|
||||||
|
|
||||||
|
alias w := watch
|
||||||
16
lua/minify.lua
Normal file
16
lua/minify.lua
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
local args = { ... }
|
||||||
|
local filename = args[1]
|
||||||
|
print(('filename: "%s"'):format(filename))
|
||||||
|
|
||||||
|
local parser = require("dumbParser")
|
||||||
|
|
||||||
|
local tokens = parser.tokenizeFile(filename)
|
||||||
|
local ast = parser.parse(tokens)
|
||||||
|
|
||||||
|
parser.minify(ast, true)
|
||||||
|
|
||||||
|
local output = parser.toLua(ast)
|
||||||
|
|
||||||
|
local f = io.open(filename, "w")
|
||||||
|
f:write(output)
|
||||||
|
f:close()
|
||||||
7
lua/src/auth.d.tl
Normal file
7
lua/src/auth.d.tl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
local record Auth
|
||||||
|
id: string
|
||||||
|
token: string
|
||||||
|
server: string
|
||||||
|
end
|
||||||
|
|
||||||
|
return Auth
|
||||||
139
lua/src/lib/framebuffer.tl
Normal file
139
lua/src/lib/framebuffer.tl
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
local record ScreenContent
|
||||||
|
x: integer
|
||||||
|
y: integer
|
||||||
|
width: integer
|
||||||
|
height: integer
|
||||||
|
blink: boolean
|
||||||
|
fg: integer
|
||||||
|
text: {string}
|
||||||
|
fg_color: {string}
|
||||||
|
bg_color: {string}
|
||||||
|
palette: {integer}
|
||||||
|
end
|
||||||
|
|
||||||
|
local record Buffer
|
||||||
|
target: term.Redirect
|
||||||
|
serialize: function(): ScreenContent
|
||||||
|
is_dirty: function(): boolean
|
||||||
|
clear_dirty: function()
|
||||||
|
end
|
||||||
|
|
||||||
|
local COLOR_LOOKUP <const> : {number: integer} = {
|
||||||
|
[colors.white] = 0x0,
|
||||||
|
[colors.orange] = 0x1,
|
||||||
|
[colors.magenta] = 0x2,
|
||||||
|
[colors.lightBlue] = 0x3,
|
||||||
|
[colors.yellow] = 0x4,
|
||||||
|
[colors.lime] = 0x5,
|
||||||
|
[colors.pink] = 0x6,
|
||||||
|
[colors.gray] = 0x7,
|
||||||
|
[colors.lightGray] = 0x8,
|
||||||
|
[colors.cyan] = 0x9,
|
||||||
|
[colors.purple] = 0xA,
|
||||||
|
[colors.blue] = 0xB,
|
||||||
|
[colors.brown] = 0xC,
|
||||||
|
[colors.green] = 0xD,
|
||||||
|
[colors.red] = 0xE,
|
||||||
|
[colors.black] = 0xF,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function wrap(parent: term.Redirect): Buffer
|
||||||
|
local x, y = parent.getCursorPos()
|
||||||
|
local width, height = parent.getSize()
|
||||||
|
local blink = parent.getCursorBlink()
|
||||||
|
local fg = COLOR_LOOKUP[parent.getTextColor()]
|
||||||
|
local palette: {number} = {}
|
||||||
|
for c = 0, 15 do
|
||||||
|
palette[c+1] = colors.packRGB(parent.getPaletteColor(2^c))
|
||||||
|
end
|
||||||
|
local dirty: boolean = false
|
||||||
|
|
||||||
|
local win = window.create(parent, 1, 1, width, height)
|
||||||
|
|
||||||
|
local overrides: table = {}
|
||||||
|
|
||||||
|
overrides.setCursorPos = function(new_x: integer, new_y: integer)
|
||||||
|
win.setCursorPos(new_x, new_y)
|
||||||
|
x = new_x
|
||||||
|
y = new_y
|
||||||
|
end
|
||||||
|
|
||||||
|
overrides.setCursorBlink = function(new_blink: boolean)
|
||||||
|
win.setCursorBlink(new_blink)
|
||||||
|
blink = new_blink
|
||||||
|
end
|
||||||
|
|
||||||
|
overrides.setTextColor = function(new_color: number)
|
||||||
|
local r = { pcall(win.setTextColor, new_color) }
|
||||||
|
if not r[1] then
|
||||||
|
error((r[2] as string):sub(8))
|
||||||
|
end
|
||||||
|
fg = COLOR_LOOKUP[new_color]
|
||||||
|
end
|
||||||
|
overrides.setTextColour = overrides.setTextColor
|
||||||
|
|
||||||
|
overrides.setPaletteColor = function(color: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
local r = { pcall(win.setPaletteColor, color, r_rgb, g, b) }
|
||||||
|
if not r[1] then
|
||||||
|
error((r[2] as string):sub(8))
|
||||||
|
end
|
||||||
|
local index = COLOR_LOOKUP[color]
|
||||||
|
if g == nil then
|
||||||
|
palette[1 + index] = r_rgb
|
||||||
|
else
|
||||||
|
palette[1 + index] = colors.packRGB(r_rgb, g, b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
overrides.setPaletteColour = overrides.setPaletteColor
|
||||||
|
|
||||||
|
local target = setmetatable(overrides, {
|
||||||
|
__index = function(_: table, k: any): any
|
||||||
|
dirty = true
|
||||||
|
return (win as table)[k]
|
||||||
|
end
|
||||||
|
}) as term.Redirect
|
||||||
|
|
||||||
|
target.setTextColor(colors.white)
|
||||||
|
target.setBackgroundColor(colors.black)
|
||||||
|
target.setCursorPos(1,1)
|
||||||
|
target.clear()
|
||||||
|
|
||||||
|
local buffer: Buffer = {
|
||||||
|
target = target
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.serialize = function(): ScreenContent
|
||||||
|
local text: {string} = {}
|
||||||
|
local fg_color: {string} = {}
|
||||||
|
local bg_color: {string} = {}
|
||||||
|
for i = 1, height do
|
||||||
|
local t, f, b = win.getLine(i)
|
||||||
|
table.insert(text, t)
|
||||||
|
table.insert(fg_color, f)
|
||||||
|
table.insert(bg_color, b)
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
x = x,
|
||||||
|
y = y,
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
blink = blink,
|
||||||
|
fg = fg,
|
||||||
|
text = text,
|
||||||
|
fg_color = fg_color,
|
||||||
|
bg_color = bg_color,
|
||||||
|
palette = palette
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
buffer.is_dirty = function(): boolean
|
||||||
|
return dirty
|
||||||
|
end
|
||||||
|
|
||||||
|
buffer.clear_dirty = function() dirty = false end
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return { wrap = wrap, Buffer = Buffer, ScreenContent = ScreenContent }
|
||||||
42
lua/src/lib/ringbuffer.tl
Normal file
42
lua/src/lib/ringbuffer.tl
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
local record Ringbuffer<T>
|
||||||
|
{T}
|
||||||
|
push: function(self: Ringbuffer<T>, el: T): boolean
|
||||||
|
pop: function(self: Ringbuffer<T>): T | nil
|
||||||
|
is_empty: function(self: Ringbuffer<T>): boolean
|
||||||
|
|
||||||
|
head: integer
|
||||||
|
n: integer
|
||||||
|
size: integer
|
||||||
|
end
|
||||||
|
|
||||||
|
local impl: table = {}
|
||||||
|
|
||||||
|
impl.push = function<T>(self: Ringbuffer<T>, el: T): boolean
|
||||||
|
if self.n == self.size then return false end
|
||||||
|
-- items are at head + 0, head + 1, ..., head + (n-1)
|
||||||
|
local tail = (self.head + self.n) % self.size
|
||||||
|
self[1 + tail] = el
|
||||||
|
self.n = self.n + 1
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.pop = function<T>(self: Ringbuffer<T>): T | nil
|
||||||
|
if self.n == 0 then return nil end
|
||||||
|
local res = self[1 + self.head]
|
||||||
|
self.head = (self.head + 1) % self.size
|
||||||
|
self.n = self.n - 1
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.is_empty = function<T>(self: Ringbuffer<T>): boolean
|
||||||
|
return self.n == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function new<T>(size: integer): Ringbuffer<T>
|
||||||
|
return setmetatable({ head = 0, n = 0, size = size }, { __index = impl })
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
new = new,
|
||||||
|
Ringbuffer = Ringbuffer
|
||||||
|
}
|
||||||
94
lua/src/lib/socket.tl
Normal file
94
lua/src/lib/socket.tl
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
local enum State
|
||||||
|
"reset"
|
||||||
|
"error"
|
||||||
|
"ok"
|
||||||
|
"viewer_connected"
|
||||||
|
end
|
||||||
|
|
||||||
|
local BAD_STATES <const> : {State: boolean} = {
|
||||||
|
["reset"] = true,
|
||||||
|
["error"] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
local type StateCallback = function(new_state: State)
|
||||||
|
|
||||||
|
local record Socket
|
||||||
|
state: State
|
||||||
|
is_bad_state: function(self: Socket): boolean
|
||||||
|
_set_state: function(self: Socket, state: State)
|
||||||
|
on_state_change: function(self: Socket, cb: StateCallback)
|
||||||
|
send: function(self: Socket, message: string)
|
||||||
|
reconnect: function(self: Socket)
|
||||||
|
close: function(self: Socket)
|
||||||
|
signal_viewer_connect: function(self: Socket, connected: boolean)
|
||||||
|
_endpoint: string
|
||||||
|
_headers: {string: string}
|
||||||
|
_callback: StateCallback
|
||||||
|
_ws: http.Websocket
|
||||||
|
end
|
||||||
|
|
||||||
|
local impl: table = {}
|
||||||
|
|
||||||
|
impl.is_bad_state = function(self: Socket): boolean
|
||||||
|
return BAD_STATES[self.state] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
impl._set_state = function(self: Socket, state: State)
|
||||||
|
self.state = state
|
||||||
|
self._callback(state)
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.on_state_change = function(self: Socket, cb: StateCallback)
|
||||||
|
self._callback = cb
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.send = function(self: Socket, message: string)
|
||||||
|
-- "message" needs to be valid JSON
|
||||||
|
-- otherwise the server will not accept it
|
||||||
|
|
||||||
|
if self:is_bad_state() then return end
|
||||||
|
|
||||||
|
local r = { pcall(self._ws.send, message) }
|
||||||
|
|
||||||
|
if r[1] == false then
|
||||||
|
if (r[2] as string):sub(-11) == "closed file" then
|
||||||
|
self:_set_state("reset")
|
||||||
|
elseif (r[2] as string):sub(-9) == "too large" then
|
||||||
|
-- TODO handle
|
||||||
|
-- the connection stays open though
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.reconnect = function(self: Socket)
|
||||||
|
local r = http.websocket(self._endpoint, self._headers)
|
||||||
|
if r ~= false then
|
||||||
|
self._ws = r as http.Websocket
|
||||||
|
self:_set_state("ok")
|
||||||
|
else
|
||||||
|
self:_set_state("error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.close = function(self: Socket)
|
||||||
|
if self:is_bad_state() then return end
|
||||||
|
self._ws.close()
|
||||||
|
end
|
||||||
|
|
||||||
|
impl.signal_viewer_connect = function(self: Socket, connected: boolean)
|
||||||
|
if self:is_bad_state() then return end --how?
|
||||||
|
local new_state: State = connected and "viewer_connected" or "ok"
|
||||||
|
self:_set_state(new_state)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function new(endpoint: string, headers: {string: string}): Socket
|
||||||
|
return setmetatable({
|
||||||
|
state = "reset",
|
||||||
|
_endpoint = endpoint,
|
||||||
|
_headers = headers,
|
||||||
|
_callback = function(_: State) end,
|
||||||
|
_ws = nil,
|
||||||
|
}, { __index = impl })
|
||||||
|
end
|
||||||
|
|
||||||
|
return { new = new, State = State, StateCallback = StateCallback, Socket = Socket }
|
||||||
165
lua/src/main.tl
Normal file
165
lua/src/main.tl
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
local json = require("vendor/json")
|
||||||
|
local Framebuffer = require("lib/framebuffer")
|
||||||
|
local Ringbuffer = require("lib/ringbuffer")
|
||||||
|
local Socket = require("lib/socket")
|
||||||
|
local auth = require("auth")
|
||||||
|
local ENDPOINT <const> = auth.server:gsub("http", "ws", 1) .. "/ipmi/computer/" .. auth.id .. "/ws"
|
||||||
|
local HEADERS <const> = { ["Authorization"] = "Bearer " .. auth.token }
|
||||||
|
|
||||||
|
print("[MAIN] Init")
|
||||||
|
|
||||||
|
local socket = Socket.new(ENDPOINT, HEADERS)
|
||||||
|
|
||||||
|
-- Set up framebuffer capture and statusline
|
||||||
|
|
||||||
|
print("[MAIN] Setup framebuffer")
|
||||||
|
|
||||||
|
local prev_term = term.current()
|
||||||
|
local orig_native = term.native
|
||||||
|
local buffer = Framebuffer.wrap(orig_native())
|
||||||
|
term.native = function(): term.Redirect
|
||||||
|
return buffer.target
|
||||||
|
end
|
||||||
|
|
||||||
|
local width, height = term.getSize()
|
||||||
|
local top_line = window.create(buffer.target, 1, 1, width, 1)
|
||||||
|
local main_view = window.create(buffer.target, 1, 2, width, height - 1)
|
||||||
|
term.redirect(main_view as term.Redirect)
|
||||||
|
|
||||||
|
local function set_bar(text: string, fg: string | nil, bg: string | nil)
|
||||||
|
fg = fg or ("9"):rep(text:len())
|
||||||
|
bg = bg or ("f"):rep(text:len())
|
||||||
|
top_line.clear()
|
||||||
|
top_line.setCursorPos(1,1)
|
||||||
|
top_line.blit(text, fg, bg)
|
||||||
|
main_view.restoreCursor()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create tasks
|
||||||
|
|
||||||
|
local bar_codes: { Socket.State: {string} } = {
|
||||||
|
["reset"] = {"[WS] RST", "78870111"},
|
||||||
|
["error"] = {"[WS] ERR", "78870EEE"},
|
||||||
|
["ok"] = {"[WS] OK\x03", "78870DD5"},
|
||||||
|
["viewer_connected"] = {"[WS] CON", "78870999"},
|
||||||
|
}
|
||||||
|
|
||||||
|
socket:on_state_change(function(new_state: Socket.State)
|
||||||
|
set_bar(table.unpack(bar_codes[new_state]))
|
||||||
|
end)
|
||||||
|
|
||||||
|
local ws_task = coroutine.create(function()
|
||||||
|
while true do
|
||||||
|
if socket:is_bad_state() then
|
||||||
|
socket:reconnect()
|
||||||
|
end
|
||||||
|
sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local report_task = coroutine.create(function()
|
||||||
|
local last_report = -1.0
|
||||||
|
while true do
|
||||||
|
local now = os.clock()
|
||||||
|
local interval = (socket.state == "viewer_connected") and 0.05 or 1
|
||||||
|
if now - last_report >= interval then
|
||||||
|
local message = json.encode({
|
||||||
|
screen = buffer.serialize()
|
||||||
|
})
|
||||||
|
socket:send(message)
|
||||||
|
last_report = now
|
||||||
|
end
|
||||||
|
sleep(0) -- until next gametick
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- basically parallel.waitForAny
|
||||||
|
|
||||||
|
local record Task
|
||||||
|
coro: thread
|
||||||
|
filter: string | nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local background_tasks: {Task} = {
|
||||||
|
{coro = ws_task},
|
||||||
|
{coro = report_task},
|
||||||
|
}
|
||||||
|
|
||||||
|
local shell_task: Task = {
|
||||||
|
coro = coroutine.create(function() shell.run("shell") end)
|
||||||
|
}
|
||||||
|
|
||||||
|
local function handle_event(e: table, pid: integer)
|
||||||
|
if e[1] == "terminate" then return end
|
||||||
|
|
||||||
|
local task = background_tasks[pid]
|
||||||
|
if task.filter == nil or task.filter == e[1] then
|
||||||
|
local ok, param = coroutine.resume(task.coro, table.unpack(e as {any}))
|
||||||
|
if not ok then
|
||||||
|
term.native = orig_native
|
||||||
|
term.redirect(term.native())
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1,1)
|
||||||
|
print(("OMEGABIG OOF @ PID %d"):format(pid))
|
||||||
|
error(param, 0)
|
||||||
|
else
|
||||||
|
task.filter = param as string
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local event_queue: Ringbuffer.Ringbuffer<table> = Ringbuffer.new(64)
|
||||||
|
event_queue:push({n = 0})
|
||||||
|
|
||||||
|
local shell_deaths: {any} = {}
|
||||||
|
|
||||||
|
local shell_running = true
|
||||||
|
while shell_running do
|
||||||
|
local e: table
|
||||||
|
|
||||||
|
if not event_queue:is_empty() then
|
||||||
|
e = event_queue:pop() as table
|
||||||
|
else
|
||||||
|
e = table.pack(os.pullEventRaw())
|
||||||
|
end
|
||||||
|
|
||||||
|
if e[1] == "websocket_message" and e[2] == ENDPOINT then
|
||||||
|
local payload = json.decode(e[3] as string) as table
|
||||||
|
if payload["type"] == "push_event" then
|
||||||
|
event_queue:push(payload["event"] as table)
|
||||||
|
elseif payload["type"] == "viewer_connect" then
|
||||||
|
socket:signal_viewer_connect(true)
|
||||||
|
elseif payload["type"] == "viewer_disconnect" then
|
||||||
|
socket:signal_viewer_connect(false)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for pid = 1, #background_tasks do
|
||||||
|
handle_event(e, pid)
|
||||||
|
end
|
||||||
|
|
||||||
|
if shell_task.filter == nil or shell_task.filter == e[1] or e[1] == "terminate" then
|
||||||
|
local ok, param = coroutine.resume(shell_task.coro, table.unpack(e as {any}))
|
||||||
|
if not ok then
|
||||||
|
-- shell died i guess?
|
||||||
|
table.insert(shell_deaths, param)
|
||||||
|
else
|
||||||
|
shell_task.filter = param as string
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if coroutine.status(shell_task.coro) == "dead" then
|
||||||
|
shell_running = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
socket:close()
|
||||||
|
|
||||||
|
term.native = orig_native
|
||||||
|
term.redirect(prev_term)
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1,1)
|
||||||
|
|
||||||
|
for i = 1, #shell_deaths do
|
||||||
|
print(shell_deaths[i])
|
||||||
|
end
|
||||||
6
lua/src/vendor/json.d.tl
vendored
Normal file
6
lua/src/vendor/json.d.tl
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
local record Json
|
||||||
|
encode: function(value: any): string
|
||||||
|
decode: function(str: string): any
|
||||||
|
end
|
||||||
|
|
||||||
|
return Json
|
||||||
388
lua/src/vendor/json.lua
vendored
Normal file
388
lua/src/vendor/json.lua
vendored
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
--
|
||||||
|
-- json.lua
|
||||||
|
--
|
||||||
|
-- Copyright (c) 2020 rxi
|
||||||
|
--
|
||||||
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
-- this software and associated documentation files (the "Software"), to deal in
|
||||||
|
-- the Software without restriction, including without limitation the rights to
|
||||||
|
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
-- of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
-- so, subject to the following conditions:
|
||||||
|
--
|
||||||
|
-- The above copyright notice and this permission notice shall be included in all
|
||||||
|
-- copies or substantial portions of the Software.
|
||||||
|
--
|
||||||
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
-- SOFTWARE.
|
||||||
|
--
|
||||||
|
|
||||||
|
local json = { _version = "0.1.2" }
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Encode
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local encode
|
||||||
|
|
||||||
|
local escape_char_map = {
|
||||||
|
[ "\\" ] = "\\",
|
||||||
|
[ "\"" ] = "\"",
|
||||||
|
[ "\b" ] = "b",
|
||||||
|
[ "\f" ] = "f",
|
||||||
|
[ "\n" ] = "n",
|
||||||
|
[ "\r" ] = "r",
|
||||||
|
[ "\t" ] = "t",
|
||||||
|
}
|
||||||
|
|
||||||
|
local escape_char_map_inv = { [ "/" ] = "/" }
|
||||||
|
for k, v in pairs(escape_char_map) do
|
||||||
|
escape_char_map_inv[v] = k
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function escape_char(c)
|
||||||
|
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_nil(val)
|
||||||
|
return "null"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_table(val, stack)
|
||||||
|
local res = {}
|
||||||
|
stack = stack or {}
|
||||||
|
|
||||||
|
-- Circular reference?
|
||||||
|
if stack[val] then error("circular reference") end
|
||||||
|
|
||||||
|
stack[val] = true
|
||||||
|
|
||||||
|
if rawget(val, 1) ~= nil or next(val) == nil then
|
||||||
|
-- Treat as array -- check keys are valid and it is not sparse
|
||||||
|
local n = 0
|
||||||
|
for k in pairs(val) do
|
||||||
|
if type(k) ~= "number" then
|
||||||
|
error("invalid table: mixed or invalid key types")
|
||||||
|
end
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
if n ~= #val then
|
||||||
|
error("invalid table: sparse array")
|
||||||
|
end
|
||||||
|
-- Encode
|
||||||
|
for i, v in ipairs(val) do
|
||||||
|
table.insert(res, encode(v, stack))
|
||||||
|
end
|
||||||
|
stack[val] = nil
|
||||||
|
return "[" .. table.concat(res, ",") .. "]"
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Treat as an object
|
||||||
|
for k, v in pairs(val) do
|
||||||
|
if type(k) ~= "string" then
|
||||||
|
error("invalid table: mixed or invalid key types")
|
||||||
|
end
|
||||||
|
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
|
||||||
|
end
|
||||||
|
stack[val] = nil
|
||||||
|
return "{" .. table.concat(res, ",") .. "}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_string(val)
|
||||||
|
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function encode_number(val)
|
||||||
|
-- Check for NaN, -inf and inf
|
||||||
|
if val ~= val or val <= -math.huge or val >= math.huge then
|
||||||
|
error("unexpected number value '" .. tostring(val) .. "'")
|
||||||
|
end
|
||||||
|
return string.format("%.14g", val)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local type_func_map = {
|
||||||
|
[ "nil" ] = encode_nil,
|
||||||
|
[ "table" ] = encode_table,
|
||||||
|
[ "string" ] = encode_string,
|
||||||
|
[ "number" ] = encode_number,
|
||||||
|
[ "boolean" ] = tostring,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encode = function(val, stack)
|
||||||
|
local t = type(val)
|
||||||
|
local f = type_func_map[t]
|
||||||
|
if f then
|
||||||
|
return f(val, stack)
|
||||||
|
end
|
||||||
|
error("unexpected type '" .. t .. "'")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function json.encode(val)
|
||||||
|
return ( encode(val) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Decode
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local parse
|
||||||
|
|
||||||
|
local function create_set(...)
|
||||||
|
local res = {}
|
||||||
|
for i = 1, select("#", ...) do
|
||||||
|
res[ select(i, ...) ] = true
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
local space_chars = create_set(" ", "\t", "\r", "\n")
|
||||||
|
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
||||||
|
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
||||||
|
local literals = create_set("true", "false", "null")
|
||||||
|
|
||||||
|
local literal_map = {
|
||||||
|
[ "true" ] = true,
|
||||||
|
[ "false" ] = false,
|
||||||
|
[ "null" ] = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local function next_char(str, idx, set, negate)
|
||||||
|
for i = idx, #str do
|
||||||
|
if set[str:sub(i, i)] ~= negate then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return #str + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function decode_error(str, idx, msg)
|
||||||
|
local line_count = 1
|
||||||
|
local col_count = 1
|
||||||
|
for i = 1, idx - 1 do
|
||||||
|
col_count = col_count + 1
|
||||||
|
if str:sub(i, i) == "\n" then
|
||||||
|
line_count = line_count + 1
|
||||||
|
col_count = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function codepoint_to_utf8(n)
|
||||||
|
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
||||||
|
local f = math.floor
|
||||||
|
if n <= 0x7f then
|
||||||
|
return string.char(n)
|
||||||
|
elseif n <= 0x7ff then
|
||||||
|
return string.char(f(n / 64) + 192, n % 64 + 128)
|
||||||
|
elseif n <= 0xffff then
|
||||||
|
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||||
|
elseif n <= 0x10ffff then
|
||||||
|
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
|
||||||
|
f(n % 4096 / 64) + 128, n % 64 + 128)
|
||||||
|
end
|
||||||
|
error( string.format("invalid unicode codepoint '%x'", n) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_unicode_escape(s)
|
||||||
|
local n1 = tonumber( s:sub(1, 4), 16 )
|
||||||
|
local n2 = tonumber( s:sub(7, 10), 16 )
|
||||||
|
-- Surrogate pair?
|
||||||
|
if n2 then
|
||||||
|
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
||||||
|
else
|
||||||
|
return codepoint_to_utf8(n1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_string(str, i)
|
||||||
|
local res = ""
|
||||||
|
local j = i + 1
|
||||||
|
local k = j
|
||||||
|
|
||||||
|
while j <= #str do
|
||||||
|
local x = str:byte(j)
|
||||||
|
|
||||||
|
if x < 32 then
|
||||||
|
decode_error(str, j, "control character in string")
|
||||||
|
|
||||||
|
elseif x == 92 then -- `\`: Escape
|
||||||
|
res = res .. str:sub(k, j - 1)
|
||||||
|
j = j + 1
|
||||||
|
local c = str:sub(j, j)
|
||||||
|
if c == "u" then
|
||||||
|
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
|
||||||
|
or str:match("^%x%x%x%x", j + 1)
|
||||||
|
or decode_error(str, j - 1, "invalid unicode escape in string")
|
||||||
|
res = res .. parse_unicode_escape(hex)
|
||||||
|
j = j + #hex
|
||||||
|
else
|
||||||
|
if not escape_chars[c] then
|
||||||
|
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
|
||||||
|
end
|
||||||
|
res = res .. escape_char_map_inv[c]
|
||||||
|
end
|
||||||
|
k = j + 1
|
||||||
|
|
||||||
|
elseif x == 34 then -- `"`: End of string
|
||||||
|
res = res .. str:sub(k, j - 1)
|
||||||
|
return res, j + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
j = j + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
decode_error(str, i, "expected closing quote for string")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_number(str, i)
|
||||||
|
local x = next_char(str, i, delim_chars)
|
||||||
|
local s = str:sub(i, x - 1)
|
||||||
|
local n = tonumber(s)
|
||||||
|
if not n then
|
||||||
|
decode_error(str, i, "invalid number '" .. s .. "'")
|
||||||
|
end
|
||||||
|
return n, x
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_literal(str, i)
|
||||||
|
local x = next_char(str, i, delim_chars)
|
||||||
|
local word = str:sub(i, x - 1)
|
||||||
|
if not literals[word] then
|
||||||
|
decode_error(str, i, "invalid literal '" .. word .. "'")
|
||||||
|
end
|
||||||
|
return literal_map[word], x
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_array(str, i)
|
||||||
|
local res = {}
|
||||||
|
local n = 1
|
||||||
|
i = i + 1
|
||||||
|
while 1 do
|
||||||
|
local x
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
-- Empty / end of array?
|
||||||
|
if str:sub(i, i) == "]" then
|
||||||
|
i = i + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Read token
|
||||||
|
x, i = parse(str, i)
|
||||||
|
res[n] = x
|
||||||
|
n = n + 1
|
||||||
|
-- Next token
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
local chr = str:sub(i, i)
|
||||||
|
i = i + 1
|
||||||
|
if chr == "]" then break end
|
||||||
|
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
||||||
|
end
|
||||||
|
return res, i
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function parse_object(str, i)
|
||||||
|
local res = {}
|
||||||
|
i = i + 1
|
||||||
|
while 1 do
|
||||||
|
local key, val
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
-- Empty / end of object?
|
||||||
|
if str:sub(i, i) == "}" then
|
||||||
|
i = i + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Read key
|
||||||
|
if str:sub(i, i) ~= '"' then
|
||||||
|
decode_error(str, i, "expected string for key")
|
||||||
|
end
|
||||||
|
key, i = parse(str, i)
|
||||||
|
-- Read ':' delimiter
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
if str:sub(i, i) ~= ":" then
|
||||||
|
decode_error(str, i, "expected ':' after key")
|
||||||
|
end
|
||||||
|
i = next_char(str, i + 1, space_chars, true)
|
||||||
|
-- Read value
|
||||||
|
val, i = parse(str, i)
|
||||||
|
-- Set
|
||||||
|
res[key] = val
|
||||||
|
-- Next token
|
||||||
|
i = next_char(str, i, space_chars, true)
|
||||||
|
local chr = str:sub(i, i)
|
||||||
|
i = i + 1
|
||||||
|
if chr == "}" then break end
|
||||||
|
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
||||||
|
end
|
||||||
|
return res, i
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local char_func_map = {
|
||||||
|
[ '"' ] = parse_string,
|
||||||
|
[ "0" ] = parse_number,
|
||||||
|
[ "1" ] = parse_number,
|
||||||
|
[ "2" ] = parse_number,
|
||||||
|
[ "3" ] = parse_number,
|
||||||
|
[ "4" ] = parse_number,
|
||||||
|
[ "5" ] = parse_number,
|
||||||
|
[ "6" ] = parse_number,
|
||||||
|
[ "7" ] = parse_number,
|
||||||
|
[ "8" ] = parse_number,
|
||||||
|
[ "9" ] = parse_number,
|
||||||
|
[ "-" ] = parse_number,
|
||||||
|
[ "t" ] = parse_literal,
|
||||||
|
[ "f" ] = parse_literal,
|
||||||
|
[ "n" ] = parse_literal,
|
||||||
|
[ "[" ] = parse_array,
|
||||||
|
[ "{" ] = parse_object,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
parse = function(str, idx)
|
||||||
|
local chr = str:sub(idx, idx)
|
||||||
|
local f = char_func_map[chr]
|
||||||
|
if f then
|
||||||
|
return f(str, idx)
|
||||||
|
end
|
||||||
|
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function json.decode(str)
|
||||||
|
if type(str) ~= "string" then
|
||||||
|
error("expected argument of type string, got " .. type(str))
|
||||||
|
end
|
||||||
|
local res, idx = parse(str, next_char(str, 1, space_chars, true))
|
||||||
|
idx = next_char(str, idx, space_chars, true)
|
||||||
|
if idx <= #str then
|
||||||
|
decode_error(str, idx, "trailing garbage")
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return json
|
||||||
7
lua/tlconfig.lua
Normal file
7
lua/tlconfig.lua
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
return {
|
||||||
|
source_dir = "src",
|
||||||
|
include_dir = {"src"},
|
||||||
|
build_dir = "out",
|
||||||
|
global_env_def = "cc",
|
||||||
|
gen_target = "5.1",
|
||||||
|
}
|
||||||
51
lua/types/colors.d.tl
Normal file
51
lua/types/colors.d.tl
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
global record colors
|
||||||
|
white: number
|
||||||
|
orange: number
|
||||||
|
magenta: number
|
||||||
|
lightBlue: number
|
||||||
|
yellow: number
|
||||||
|
lime: number
|
||||||
|
pink: number
|
||||||
|
gray: number
|
||||||
|
lightGray: number
|
||||||
|
cyan: number
|
||||||
|
purple: number
|
||||||
|
blue: number
|
||||||
|
brown: number
|
||||||
|
green: number
|
||||||
|
red: number
|
||||||
|
black: number
|
||||||
|
|
||||||
|
combine: function(...: number): number
|
||||||
|
subtract: function(colors: number, ...: number): number
|
||||||
|
test: function(colors: number, color: number): boolean
|
||||||
|
packRGB: function(r: number, g: number, b: number): number
|
||||||
|
unpackRGB: function(rgb: number): number, number, number
|
||||||
|
toBlit: function(color: number): string
|
||||||
|
end
|
||||||
|
|
||||||
|
global record colours
|
||||||
|
white: number
|
||||||
|
orange: number
|
||||||
|
magenta: number
|
||||||
|
lightBlue: number
|
||||||
|
yellow: number
|
||||||
|
lime: number
|
||||||
|
pink: number
|
||||||
|
grey: number
|
||||||
|
lightGrey: number
|
||||||
|
cyan: number
|
||||||
|
purple: number
|
||||||
|
blue: number
|
||||||
|
brown: number
|
||||||
|
green: number
|
||||||
|
red: number
|
||||||
|
black: number
|
||||||
|
|
||||||
|
combine: function(...: number): number
|
||||||
|
subtract: function(colors: number, ...: number): number
|
||||||
|
test: function(colors: number, color: number): boolean
|
||||||
|
packRGB: function(r: number, g: number, b: number): number
|
||||||
|
unpackRGB: function(rgb: number): number, number, number
|
||||||
|
toBlit: function(color: number): string
|
||||||
|
end
|
||||||
70
lua/types/http.d.tl
Normal file
70
lua/types/http.d.tl
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
global record http
|
||||||
|
record Response
|
||||||
|
getResponseCode: function(): integer, string
|
||||||
|
getResponseHeaders: function(): {string: string}
|
||||||
|
read: function(count: integer | nil): integer, string | nil
|
||||||
|
readAll: function(): string | nil
|
||||||
|
readLine: function(withTrailing: boolean | nil): string | nil
|
||||||
|
seek: function(
|
||||||
|
whence: string | nil,
|
||||||
|
offset: integer | nil
|
||||||
|
): integer | nil, nil | string
|
||||||
|
close: function()
|
||||||
|
end
|
||||||
|
|
||||||
|
record _RequestParams
|
||||||
|
url: string
|
||||||
|
body: string | nil
|
||||||
|
headers: {string: string} | nil
|
||||||
|
binary: boolean | nil
|
||||||
|
method: string | nil
|
||||||
|
redirect: boolean | nil
|
||||||
|
end
|
||||||
|
|
||||||
|
request: function(
|
||||||
|
url_or_params: string | _RequestParams,
|
||||||
|
body: string | nil,
|
||||||
|
headers: {string: string} | nil,
|
||||||
|
binary: boolean | nil
|
||||||
|
)
|
||||||
|
|
||||||
|
record _GetParams
|
||||||
|
url: string
|
||||||
|
headers: {string: string} | nil
|
||||||
|
binary: boolean | nil
|
||||||
|
method: string | nil
|
||||||
|
redirect: boolean | nil
|
||||||
|
end
|
||||||
|
|
||||||
|
get: function(
|
||||||
|
url_or_params: string | _GetParams,
|
||||||
|
headers: {string: string} | nil,
|
||||||
|
binary: boolean | nil
|
||||||
|
): Response | nil, nil | string, nil | Response
|
||||||
|
|
||||||
|
post: function(
|
||||||
|
url_or_params: string | _RequestParams,
|
||||||
|
body: string | nil,
|
||||||
|
headers: {string: string} | nil,
|
||||||
|
binary: boolean | nil
|
||||||
|
): Response | nil, nil | string, nil | Response
|
||||||
|
|
||||||
|
checkURLAsync: function(url: string): boolean, string | nil
|
||||||
|
checkURL: function(url: string): boolean, string | nil
|
||||||
|
|
||||||
|
record Websocket
|
||||||
|
receive: function(timeout: number | nil): string | nil, nil | boolean
|
||||||
|
send: function(message: any, binary: boolean | nil)
|
||||||
|
close: function()
|
||||||
|
end
|
||||||
|
|
||||||
|
websocket: function(
|
||||||
|
url: string,
|
||||||
|
headers: {string: string} | nil
|
||||||
|
): Websocket | boolean, nil | string
|
||||||
|
|
||||||
|
websocketAsync: function(
|
||||||
|
url: string,
|
||||||
|
headers: {string: string} | nil
|
||||||
|
)
|
||||||
|
end
|
||||||
27
lua/types/os.d.tl
Normal file
27
lua/types/os.d.tl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
global record os
|
||||||
|
pullEvent: function(filter: string | nil): string, any...
|
||||||
|
pullEventRaw: function(filter: string | nil): string, any...
|
||||||
|
sleep: function(time: number)
|
||||||
|
version: function(): string
|
||||||
|
run: function(env: table, path: string, ...: any): boolean
|
||||||
|
queueEvent: function(name: string, ...: any)
|
||||||
|
startTimer: function(time: number): integer
|
||||||
|
cancelTimer: function(token: integer)
|
||||||
|
setAlarm: function(time: number): integer
|
||||||
|
cancelAlarm: function(token: integer)
|
||||||
|
shutdown: function()
|
||||||
|
reboot: function()
|
||||||
|
getComputerID: function(): integer
|
||||||
|
computerID: function(): integer
|
||||||
|
getComputerLabel: function(): string
|
||||||
|
computerLabel: function(): string
|
||||||
|
setComputerLabel: function(label: string | nil)
|
||||||
|
clock: function(): number
|
||||||
|
time: function(locale: string | nil): number
|
||||||
|
time: function(locale: table): integer
|
||||||
|
day: function(args: string | nil): integer
|
||||||
|
epoch: function(args: string | nil): integer
|
||||||
|
date: function(): string
|
||||||
|
date: function(format: string): string | table
|
||||||
|
date: function(format: string, time: number): string | table
|
||||||
|
end
|
||||||
4
lua/types/parallel.d.tl
Normal file
4
lua/types/parallel.d.tl
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
global record parallel
|
||||||
|
waitForAny: function(...: function)
|
||||||
|
waitForAll: function(...: function)
|
||||||
|
end
|
||||||
33
lua/types/shell.d.tl
Normal file
33
lua/types/shell.d.tl
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
global record shell
|
||||||
|
execute: function(command: string, ...: string): boolean
|
||||||
|
run: function(...: string): boolean
|
||||||
|
exit: function()
|
||||||
|
dir: function(): string
|
||||||
|
setDir: function(dir: string)
|
||||||
|
path: function(): string
|
||||||
|
setPath: function(path: string)
|
||||||
|
resolve: function(path: string): string
|
||||||
|
resolveProgram: function(command: string): string | nil
|
||||||
|
programs: function(include_hidden: boolean | nil): {string}
|
||||||
|
complete: function(sLine: string): {string} | nil
|
||||||
|
completeProgram: function(program: string): {string}
|
||||||
|
|
||||||
|
type _CompletionFunction = function(
|
||||||
|
shell: table,
|
||||||
|
index: integer,
|
||||||
|
argument: string,
|
||||||
|
previous: {string}
|
||||||
|
): {string} | nil
|
||||||
|
setCompletionFunction: function(program: string, complete: _CompletionFunction)
|
||||||
|
|
||||||
|
record _CompletionInfo
|
||||||
|
fnComplete: function
|
||||||
|
end
|
||||||
|
getCompletionInfo: function(): {string: _CompletionInfo}
|
||||||
|
getRunningProgram: function(): string
|
||||||
|
setAlias: function(command: string, program: string)
|
||||||
|
clearAlias: function(command: string)
|
||||||
|
aliases: function(): {string:string}
|
||||||
|
openTab: function(...: string): integer
|
||||||
|
switchTab: function(id: integer)
|
||||||
|
end
|
||||||
65
lua/types/term.d.tl
Normal file
65
lua/types/term.d.tl
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
global record term
|
||||||
|
|
||||||
|
record Redirect
|
||||||
|
write: function(text: string)
|
||||||
|
blit: function(text: string, textColor: string, backgroundColor: string)
|
||||||
|
scroll: function(y: integer)
|
||||||
|
clear: function()
|
||||||
|
clearLine: function()
|
||||||
|
|
||||||
|
getCursorPos: function(): integer, integer
|
||||||
|
setCursorPos: function(x: integer, y: integer)
|
||||||
|
getCursorBlink: function(): boolean
|
||||||
|
setCursorBlink: function(blink: boolean)
|
||||||
|
getSize: function(): integer, integer
|
||||||
|
|
||||||
|
isColor: function(): boolean
|
||||||
|
isColour: function(): boolean
|
||||||
|
getTextColor: function(): number
|
||||||
|
getTextColour: function(): number
|
||||||
|
setTextColor: function(color: number)
|
||||||
|
setTextColour: function(colour: number)
|
||||||
|
getBackgroundColor: function(): number
|
||||||
|
getBackgroundColour: function(): number
|
||||||
|
setBackgroundColor: function(color: number)
|
||||||
|
setBackgroundColour: function(colour: number)
|
||||||
|
getPaletteColor: function(color: number): number, number, number
|
||||||
|
getPaletteColour: function(colour: number): number, number, number
|
||||||
|
setPaletteColour: function(color: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
setPaletteColor: function(colour: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
write: function(text: string)
|
||||||
|
blit: function(text: string, textColor: string, backgroundColor: string)
|
||||||
|
scroll: function(y: integer)
|
||||||
|
clear: function()
|
||||||
|
clearLine: function()
|
||||||
|
|
||||||
|
getCursorPos: function(): integer, integer
|
||||||
|
setCursorPos: function(x: integer, y: integer)
|
||||||
|
getCursorBlink: function(): boolean
|
||||||
|
setCursorBlink: function(blink: boolean)
|
||||||
|
getSize: function(): integer, integer
|
||||||
|
|
||||||
|
isColor: function(): boolean
|
||||||
|
isColour: function(): boolean
|
||||||
|
getTextColor: function(): number
|
||||||
|
getTextColour: function(): number
|
||||||
|
setTextColor: function(color: number)
|
||||||
|
setTextColour: function(colour: number)
|
||||||
|
getBackgroundColor: function(): number
|
||||||
|
getBackgroundColour: function(): number
|
||||||
|
setBackgroundColor: function(color: number)
|
||||||
|
setBackgroundColour: function(colour: number)
|
||||||
|
getPaletteColor: function(color: number): number, number, number
|
||||||
|
getPaletteColour: function(colour: number): number, number, number
|
||||||
|
setPaletteColour: function(color: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
setPaletteColor: function(colour: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
|
||||||
|
nativePaletteColor: function(color: number): number, number, number
|
||||||
|
nativePaletteColour: function(colour: number): number, number, number
|
||||||
|
|
||||||
|
redirect: function(target: Redirect): Redirect
|
||||||
|
current: function(): Redirect
|
||||||
|
native: function(): Redirect
|
||||||
|
end
|
||||||
40
lua/types/window.d.tl
Normal file
40
lua/types/window.d.tl
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
global record window
|
||||||
|
record Window
|
||||||
|
write: function(text: string)
|
||||||
|
blit: function(text: string, textColor: string, backgroundColor: string)
|
||||||
|
scroll: function(y: integer)
|
||||||
|
clear: function()
|
||||||
|
clearLine: function()
|
||||||
|
|
||||||
|
getCursorPos: function(): integer, integer
|
||||||
|
setCursorPos: function(x: integer, y: integer)
|
||||||
|
getCursorBlink: function(): boolean
|
||||||
|
setCursorBlink: function(blink: boolean)
|
||||||
|
getSize: function(): integer, integer
|
||||||
|
|
||||||
|
isColor: function(): boolean
|
||||||
|
isColour: function(): boolean
|
||||||
|
getTextColor: function(): number
|
||||||
|
getTextColour: function(): number
|
||||||
|
setTextColor: function(color: number)
|
||||||
|
setTextColour: function(colour: number)
|
||||||
|
getBackgroundColor: function(): number
|
||||||
|
getBackgroundColour: function(): number
|
||||||
|
setBackgroundColor: function(color: number)
|
||||||
|
setBackgroundColour: function(colour: number)
|
||||||
|
getPaletteColor: function(color: number): number, number, number
|
||||||
|
getPaletteColour: function(colour: number): number, number, number
|
||||||
|
setPaletteColour: function(color: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
setPaletteColor: function(colour: number, r_rgb: number, g: number | nil, b: number | nil)
|
||||||
|
|
||||||
|
getLine: function(y: integer): string, string, string
|
||||||
|
setVisible: function(visible: boolean)
|
||||||
|
isVisible: function(): boolean
|
||||||
|
redraw: function()
|
||||||
|
restoreCursor: function()
|
||||||
|
getPosition: function(): integer, integer
|
||||||
|
reposition: function(new_x: integer, new_y: integer, new_width: integer | nil, new_height: integer | nil, new_parent: term.Redirect | nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
create: function(parent: term.Redirect, x: integer, y: integer, width: integer, height: integer, startVisible: boolean | nil): Window
|
||||||
|
end
|
||||||
3
server/.gitignore
vendored
3
server/.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
.venv
|
.venv
|
||||||
secret.env
|
secret.env
|
||||||
tiles
|
unmined-out
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
|
db.env
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Requires [poetry](https://archlinux.org/packages/community/any/python-poetry/)
|
|||||||
$ cd ../frontend
|
$ cd ../frontend
|
||||||
$ npm run dev
|
$ npm run dev
|
||||||
# in a different terminal
|
# in a different terminal
|
||||||
$ DEV_MODE=1 poetry run uvicorn server:app --reload
|
$ DEV_MODE=1 poetry run uvicorn server:app --reload --env-file db.env
|
||||||
```
|
```
|
||||||
|
|
||||||
### prod
|
### prod
|
||||||
@@ -21,5 +21,5 @@ $ DEV_MODE=1 poetry run uvicorn server:app --reload
|
|||||||
$ pushd ../frontend
|
$ pushd ../frontend
|
||||||
$ npm run build
|
$ npm run build
|
||||||
$ popd
|
$ popd
|
||||||
$ poetry run uvicorn server:app
|
$ poetry run uvicorn server:app --env-file db.env
|
||||||
```
|
```
|
||||||
1
server/db.env.example
Normal file
1
server/db.env.example
Normal file
@@ -0,0 +1 @@
|
|||||||
|
MONGO_URI="mongodb://user:pass@localhost:27017/"
|
||||||
96
server/dummy-client.py
Normal file
96
server/dummy-client.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import websockets
|
||||||
|
|
||||||
|
ENDPOINT = "ws://localhost:8000/ipmi/computer/8b9faf9f-9470-4a50-b405-0af5f0152550/ws"
|
||||||
|
|
||||||
|
|
||||||
|
def gen_payload(tick: int):
|
||||||
|
return {
|
||||||
|
"x": 3,
|
||||||
|
"y": 4,
|
||||||
|
"width": 39,
|
||||||
|
"height": 13,
|
||||||
|
"blink": True,
|
||||||
|
"fg": 0,
|
||||||
|
"text": [
|
||||||
|
"[WS] OK\u0003 ",
|
||||||
|
"FG 0123456789ABCDEF ",
|
||||||
|
"BG 0123456789ABCDEF ",
|
||||||
|
" ",
|
||||||
|
f"Tick: {tick:8d} ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
],
|
||||||
|
"fg_color": [
|
||||||
|
"78870dd50000000000000000000000000000000",
|
||||||
|
"0000123456789abcdef00000000000000000000",
|
||||||
|
"000f00000000000000000000000000000000000",
|
||||||
|
"440000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000",
|
||||||
|
],
|
||||||
|
"bg_color": [
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"ffffffffffffffffff0ffffffffffffffffffff",
|
||||||
|
"fff0123456789abcdefffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
"fffffffffffffffffffffffffffffffffffffff",
|
||||||
|
],
|
||||||
|
"palette": [
|
||||||
|
15790320,
|
||||||
|
15905331,
|
||||||
|
15040472,
|
||||||
|
10072818,
|
||||||
|
14605932,
|
||||||
|
8375321,
|
||||||
|
15905484,
|
||||||
|
5000268,
|
||||||
|
10066329,
|
||||||
|
5020082,
|
||||||
|
11691749,
|
||||||
|
3368652,
|
||||||
|
8349260,
|
||||||
|
5744206,
|
||||||
|
13388876,
|
||||||
|
1118481,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
tick = 0
|
||||||
|
|
||||||
|
async with websockets.connect(ENDPOINT) as socket:
|
||||||
|
while True:
|
||||||
|
await socket.send(json.dumps({"screen": gen_payload(tick)}))
|
||||||
|
await asyncio.sleep(1 / 20)
|
||||||
|
tick += 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
asyncio.run(main())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("this handler gets it")
|
||||||
1
server/lua
Symbolic link
1
server/lua
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../lua/out
|
||||||
425
server/poetry.lock
generated
425
server/poetry.lock
generated
@@ -17,7 +17,7 @@ trio = ["trio (>=0.16)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "Authlib"
|
name = "Authlib"
|
||||||
version = "1.0.1"
|
version = "1.1.0"
|
||||||
description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients."
|
description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -28,7 +28,7 @@ cryptography = ">=3.2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2022.6.15"
|
version = "2022.9.24"
|
||||||
description = "Python package for providing Mozilla's CA Bundle."
|
description = "Python package for providing Mozilla's CA Bundle."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -66,7 +66,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "37.0.4"
|
version = "38.0.1"
|
||||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -76,10 +76,10 @@ python-versions = ">=3.6"
|
|||||||
cffi = ">=1.12"
|
cffi = ">=1.12"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx_rtd_theme"]
|
docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"]
|
||||||
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
|
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
|
||||||
pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
|
pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
|
||||||
sdist = ["setuptools_rust (>=0.11.4)"]
|
sdist = ["setuptools-rust (>=0.11.4)"]
|
||||||
ssh = ["bcrypt (>=3.1.5)"]
|
ssh = ["bcrypt (>=3.1.5)"]
|
||||||
test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"]
|
test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"]
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ socks = ["socksio (>=1.0.0,<2.0.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httptools"
|
name = "httptools"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
description = "A collection of framework independent HTTP protocol utils."
|
description = "A collection of framework independent HTTP protocol utils."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -160,7 +160,7 @@ socks = ["socksio (>=1.0.0,<2.0.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.3"
|
version = "3.4"
|
||||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -196,6 +196,26 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "motor"
|
||||||
|
version = "3.0.0"
|
||||||
|
description = "Non-blocking MongoDB driver for Tornado or asyncio"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pymongo = ">=4.1,<5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
aws = ["pymongo[aws] (>=4.1,<5)"]
|
||||||
|
encryption = ["pymongo[encryption] (>=4.1,<5)"]
|
||||||
|
gssapi = ["pymongo[gssapi] (>=4.1,<5)"]
|
||||||
|
ocsp = ["pymongo[ocsp] (>=4.1,<5)"]
|
||||||
|
snappy = ["pymongo[snappy] (>=4.1,<5)"]
|
||||||
|
srv = ["pymongo[srv] (>=4.1,<5)"]
|
||||||
|
zstd = ["pymongo[zstd] (>=4.1,<5)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pycparser"
|
name = "pycparser"
|
||||||
version = "2.21"
|
version = "2.21"
|
||||||
@@ -206,7 +226,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "1.10.1"
|
version = "1.10.2"
|
||||||
description = "Data validation and settings management using python type hints"
|
description = "Data validation and settings management using python type hints"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -219,6 +239,23 @@ typing-extensions = ">=4.1.0"
|
|||||||
dotenv = ["python-dotenv (>=0.10.4)"]
|
dotenv = ["python-dotenv (>=0.10.4)"]
|
||||||
email = ["email-validator (>=1.0.3)"]
|
email = ["email-validator (>=1.0.3)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pymongo"
|
||||||
|
version = "4.2.0"
|
||||||
|
description = "Python driver for MongoDB <http://www.mongodb.org>"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
aws = ["pymongo-auth-aws (<2.0.0)"]
|
||||||
|
encryption = ["pymongocrypt (>=1.3.0,<2.0.0)"]
|
||||||
|
gssapi = ["pykerberos"]
|
||||||
|
ocsp = ["certifi", "pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)"]
|
||||||
|
snappy = ["python-snappy"]
|
||||||
|
srv = ["dnspython (>=1.16.0,<3.0.0)"]
|
||||||
|
zstd = ["zstandard"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dotenv"
|
name = "python-dotenv"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
@@ -306,20 +343,20 @@ standard = ["colorama (>=0.4)", "httptools (>=0.4.0)", "python-dotenv (>=0.13)",
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uvloop"
|
name = "uvloop"
|
||||||
version = "0.16.0"
|
version = "0.17.0"
|
||||||
description = "Fast implementation of asyncio event loop on top of libuv"
|
description = "Fast implementation of asyncio event loop on top of libuv"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["Cython (>=0.29.24,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=19.0.0,<19.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
|
dev = ["Cython (>=0.29.32,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
|
||||||
docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
|
docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
|
||||||
test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=19.0.0,<19.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"]
|
test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "watchfiles"
|
name = "watchfiles"
|
||||||
version = "0.16.1"
|
version = "0.17.0"
|
||||||
description = "Simple, modern and high performance file watching and code reload in python."
|
description = "Simple, modern and high performance file watching and code reload in python."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@@ -339,7 +376,7 @@ python-versions = ">=3.7"
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "302816b99259a9b9b37589635b575875a945d1d5ebead0f9ea7795837cd62e71"
|
content-hash = "e769d7cd6752aa62e9f4a4516cb1d612a0205846799757f44e543ee561229804"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
anyio = [
|
anyio = [
|
||||||
@@ -347,12 +384,12 @@ anyio = [
|
|||||||
{file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
|
{file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
|
||||||
]
|
]
|
||||||
Authlib = [
|
Authlib = [
|
||||||
{file = "Authlib-1.0.1-py2.py3-none-any.whl", hash = "sha256:1286e2d5ef5bfe5a11cc2d0a0d1031f0393f6ce4d61f5121cfe87fa0054e98bd"},
|
{file = "Authlib-1.1.0-py2.py3-none-any.whl", hash = "sha256:be4b6a1dea51122336c210a6945b27a105b9ac572baffd15b07bcff4376c1523"},
|
||||||
{file = "Authlib-1.0.1.tar.gz", hash = "sha256:6e74a4846ac36dfc882b3cc2fbd3d9eb410a627f2f2dc11771276655345223b1"},
|
{file = "Authlib-1.1.0.tar.gz", hash = "sha256:0a270c91409fc2b7b0fbee6996e09f2ee3187358762111a9a4225c874b94e891"},
|
||||||
]
|
]
|
||||||
certifi = [
|
certifi = [
|
||||||
{file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
|
{file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
|
||||||
{file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
|
{file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
|
||||||
]
|
]
|
||||||
cffi = [
|
cffi = [
|
||||||
{file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
|
{file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
|
||||||
@@ -429,28 +466,32 @@ colorama = [
|
|||||||
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
||||||
]
|
]
|
||||||
cryptography = [
|
cryptography = [
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:549153378611c0cca1042f20fd9c5030d37a72f634c9326e225c9f666d472884"},
|
{file = "cryptography-38.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a958c52505c8adf0d3822703078580d2c0456dd1d27fabfb6f76fe63d2971cd6"},
|
{file = "cryptography-38.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f721d1885ecae9078c3f6bbe8a88bc0786b6e749bf32ccec1ef2b18929a05046"},
|
{file = "cryptography-38.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3d41b965b3380f10e4611dbae366f6dc3cefc7c9ac4e8842a806b9672ae9add5"},
|
{file = "cryptography-38.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80f49023dd13ba35f7c34072fa17f604d2f19bf0989f292cedf7ab5770b87a0b"},
|
{file = "cryptography-38.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2dcb0b3b63afb6df7fd94ec6fbddac81b5492513f7b0436210d390c14d46ee8"},
|
{file = "cryptography-38.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:b7f8dd0d4c1f21759695c05a5ec8536c12f31611541f8904083f3dc582604280"},
|
{file = "cryptography-38.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:30788e070800fec9bbcf9faa71ea6d8068f5136f60029759fd8c3efec3c9dcb3"},
|
{file = "cryptography-38.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:190f82f3e87033821828f60787cfa42bff98404483577b591429ed99bed39d59"},
|
{file = "cryptography-38.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-win32.whl", hash = "sha256:b62439d7cd1222f3da897e9a9fe53bbf5c104fff4d60893ad1355d4c14a24157"},
|
{file = "cryptography-38.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294"},
|
||||||
{file = "cryptography-37.0.4-cp36-abi3-win_amd64.whl", hash = "sha256:f7a6de3e98771e183645181b3627e2563dcde3ce94a9e42a3f427d2255190327"},
|
{file = "cryptography-38.0.1-cp36-abi3-win32.whl", hash = "sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0"},
|
||||||
{file = "cryptography-37.0.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc95ed67b6741b2607298f9ea4932ff157e570ef456ef7ff0ef4884a134cc4b"},
|
{file = "cryptography-38.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a"},
|
||||||
{file = "cryptography-37.0.4-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9"},
|
{file = "cryptography-38.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d"},
|
||||||
{file = "cryptography-37.0.4-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:e007f052ed10cc316df59bc90fbb7ff7950d7e2919c9757fd42a2b8ecf8a5f67"},
|
{file = "cryptography-38.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9"},
|
||||||
{file = "cryptography-37.0.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bc997818309f56c0038a33b8da5c0bfbb3f1f067f315f9abd6fc07ad359398d"},
|
{file = "cryptography-38.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d"},
|
||||||
{file = "cryptography-37.0.4-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:d204833f3c8a33bbe11eda63a54b1aad7aa7456ed769a982f21ec599ba5fa282"},
|
{file = "cryptography-38.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818"},
|
||||||
{file = "cryptography-37.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:75976c217f10d48a8b5a8de3d70c454c249e4b91851f6838a4e48b8f41eb71aa"},
|
{file = "cryptography-38.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6"},
|
||||||
{file = "cryptography-37.0.4-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:7099a8d55cd49b737ffc99c17de504f2257e3787e02abe6d1a6d136574873441"},
|
{file = "cryptography-38.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750"},
|
||||||
{file = "cryptography-37.0.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2be53f9f5505673eeda5f2736bea736c40f051a739bfae2f92d18aed1eb54596"},
|
{file = "cryptography-38.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013"},
|
||||||
{file = "cryptography-37.0.4-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:91ce48d35f4e3d3f1d83e29ef4a9267246e6a3be51864a5b7d2247d5086fa99a"},
|
{file = "cryptography-38.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5"},
|
||||||
{file = "cryptography-37.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab"},
|
{file = "cryptography-38.0.1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61"},
|
||||||
{file = "cryptography-37.0.4.tar.gz", hash = "sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82"},
|
{file = "cryptography-38.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac"},
|
||||||
|
{file = "cryptography-38.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb"},
|
||||||
|
{file = "cryptography-38.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a"},
|
||||||
|
{file = "cryptography-38.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b"},
|
||||||
|
{file = "cryptography-38.0.1.tar.gz", hash = "sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7"},
|
||||||
]
|
]
|
||||||
fastapi = [
|
fastapi = [
|
||||||
{file = "fastapi-0.81.0-py3-none-any.whl", hash = "sha256:9ac5f5d252b4b394df29accb1ed4bedf30e0e87fc6eb7ec75e1449fa040bfc17"},
|
{file = "fastapi-0.81.0-py3-none-any.whl", hash = "sha256:9ac5f5d252b4b394df29accb1ed4bedf30e0e87fc6eb7ec75e1449fa040bfc17"},
|
||||||
@@ -465,48 +506,55 @@ httpcore = [
|
|||||||
{file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"},
|
{file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"},
|
||||||
]
|
]
|
||||||
httptools = [
|
httptools = [
|
||||||
{file = "httptools-0.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcddfe70553be717d9745990dfdb194e22ee0f60eb8f48c0794e7bfeda30d2d5"},
|
{file = "httptools-0.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f470c79061599a126d74385623ff4744c4e0f4a0997a353a44923c0b561ee51"},
|
||||||
{file = "httptools-0.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1ee0b459257e222b878a6c09ccf233957d3a4dcb883b0847640af98d2d9aac23"},
|
{file = "httptools-0.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e90491a4d77d0cb82e0e7a9cb35d86284c677402e4ce7ba6b448ccc7325c5421"},
|
||||||
{file = "httptools-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceafd5e960b39c7e0d160a1936b68eb87c5e79b3979d66e774f0c77d4d8faaed"},
|
{file = "httptools-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1d2357f791b12d86faced7b5736dea9ef4f5ecdc6c3f253e445ee82da579449"},
|
||||||
{file = "httptools-0.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fdb9f9ed79bc6f46b021b3319184699ba1a22410a82204e6e89c774530069683"},
|
{file = "httptools-0.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f90cd6fd97c9a1b7fe9215e60c3bd97336742a0857f00a4cb31547bc22560c2"},
|
||||||
{file = "httptools-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:abe829275cdd4174b4c4e65ad718715d449e308d59793bf3a931ee1bf7e7b86c"},
|
{file = "httptools-0.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5230a99e724a1bdbbf236a1b58d6e8504b912b0552721c7c6b8570925ee0ccde"},
|
||||||
{file = "httptools-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7af6bdbd21a2a25d6784f6d67f44f5df33ef39b6159543b9f9064d365c01f919"},
|
{file = "httptools-0.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a47a34f6015dd52c9eb629c0f5a8a5193e47bf2a12d9a3194d231eaf1bc451a"},
|
||||||
{file = "httptools-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d1fe6b6661022fd6cac541f54a4237496b246e6f1c0a6b41998ee08a1135afe"},
|
{file = "httptools-0.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:24bb4bb8ac3882f90aa95403a1cb48465de877e2d5298ad6ddcfdebec060787d"},
|
||||||
{file = "httptools-0.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:48e48530d9b995a84d1d89ae6b3ec4e59ea7d494b150ac3bbc5e2ac4acce92cd"},
|
{file = "httptools-0.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e67d4f8734f8054d2c4858570cc4b233bf753f56e85217de4dfb2495904cf02e"},
|
||||||
{file = "httptools-0.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a113789e53ac1fa26edf99856a61e4c493868e125ae0dd6354cf518948fbbd5c"},
|
{file = "httptools-0.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e5eefc58d20e4c2da82c78d91b2906f1a947ef42bd668db05f4ab4201a99f49"},
|
||||||
{file = "httptools-0.4.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e2eb957787cbb614a0f006bfc5798ff1d90ac7c4dd24854c84edbdc8c02369e"},
|
{file = "httptools-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0297822cea9f90a38df29f48e40b42ac3d48a28637368f3ec6d15eebefd182f9"},
|
||||||
{file = "httptools-0.4.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:7ee9f226acab9085037582c059d66769862706e8e8cd2340470ceb8b3850873d"},
|
{file = "httptools-0.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:557be7fbf2bfa4a2ec65192c254e151684545ebab45eca5d50477d562c40f986"},
|
||||||
{file = "httptools-0.4.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:701e66b59dd21a32a274771238025d58db7e2b6ecebbab64ceff51b8e31527ae"},
|
{file = "httptools-0.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:54465401dbbec9a6a42cf737627fb0f014d50dc7365a6b6cd57753f151a86ff0"},
|
||||||
{file = "httptools-0.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6a1a7dfc1f9c78a833e2c4904757a0f47ce25d08634dd2a52af394eefe5f9777"},
|
{file = "httptools-0.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4d9ebac23d2de960726ce45f49d70eb5466725c0087a078866043dad115f850f"},
|
||||||
{file = "httptools-0.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:903f739c9fb78dab8970b0f3ea51f21955b24b45afa77b22ff0e172fc11ef111"},
|
{file = "httptools-0.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:e8a34e4c0ab7b1ca17b8763613783e2458e77938092c18ac919420ab8655c8c1"},
|
||||||
{file = "httptools-0.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54bbd295f031b866b9799dd39cb45deee81aca036c9bff9f58ca06726f6494f1"},
|
{file = "httptools-0.5.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f659d7a48401158c59933904040085c200b4be631cb5f23a7d561fbae593ec1f"},
|
||||||
{file = "httptools-0.4.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3194f6d6443befa8d4db16c1946b2fc428a3ceb8ab32eb6f09a59f86104dc1a0"},
|
{file = "httptools-0.5.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1616b3ba965cd68e6f759eeb5d34fbf596a79e84215eeceebf34ba3f61fdc7"},
|
||||||
{file = "httptools-0.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cd1295f52971097f757edfbfce827b6dbbfb0f7a74901ee7d4933dff5ad4c9af"},
|
{file = "httptools-0.5.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3625a55886257755cb15194efbf209584754e31d336e09e2ffe0685a76cb4b60"},
|
||||||
{file = "httptools-0.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:20a45bcf22452a10fa8d58b7dbdb474381f6946bf5b8933e3662d572bc61bae4"},
|
{file = "httptools-0.5.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:72ad589ba5e4a87e1d404cc1cb1b5780bfcb16e2aec957b88ce15fe879cc08ca"},
|
||||||
{file = "httptools-0.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d1f27bb0f75bef722d6e22dc609612bfa2f994541621cd2163f8c943b6463dfe"},
|
{file = "httptools-0.5.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:850fec36c48df5a790aa735417dca8ce7d4b48d59b3ebd6f83e88a8125cde324"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7f7bfb74718f52d5ed47d608d507bf66d3bc01d4a8b3e6dd7134daaae129357b"},
|
{file = "httptools-0.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f222e1e9d3f13b68ff8a835574eda02e67277d51631d69d7cf7f8e07df678c86"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a522d12e2ddbc2e91842ffb454a1aeb0d47607972c7d8fc88bd0838d97fb8a2a"},
|
{file = "httptools-0.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3cb8acf8f951363b617a8420768a9f249099b92e703c052f9a51b66342eea89b"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2db44a0b294d317199e9f80123e72c6b005c55b625b57fae36de68670090fa48"},
|
{file = "httptools-0.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550059885dc9c19a072ca6d6735739d879be3b5959ec218ba3e013fd2255a11b"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c286985b5e194ca0ebb2908d71464b9be8f17cc66d6d3e330e8d5407248f56ad"},
|
{file = "httptools-0.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a04fe458a4597aa559b79c7f48fe3dceabef0f69f562daf5c5e926b153817281"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3a4e165ca6204f34856b765d515d558dc84f1352033b8721e8d06c3e44930c3"},
|
{file = "httptools-0.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d0c1044bce274ec6711f0770fd2d5544fe392591d204c68328e60a46f88843b"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:72aa3fbe636b16d22e04b5a9d24711b043495e0ecfe58080addf23a1a37f3409"},
|
{file = "httptools-0.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c6eeefd4435055a8ebb6c5cc36111b8591c192c56a95b45fe2af22d9881eee25"},
|
||||||
{file = "httptools-0.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9967d9758df505975913304c434cb9ab21e2c609ad859eb921f2f615a038c8de"},
|
{file = "httptools-0.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5b65be160adcd9de7a7e6413a4966665756e263f0d5ddeffde277ffeee0576a5"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f72b5d24d6730035128b238decdc4c0f2104b7056a7ca55cf047c106842ec890"},
|
{file = "httptools-0.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fe9c766a0c35b7e3d6b6939393c8dfdd5da3ac5dec7f971ec9134f284c6c36d6"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:29bf97a5c532da9c7a04de2c7a9c31d1d54f3abd65a464119b680206bbbb1055"},
|
{file = "httptools-0.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:85b392aba273566c3d5596a0a490978c085b79700814fb22bfd537d381dd230c"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98993805f1e3cdb53de4eed02b55dcc953cdf017ba7bbb2fd89226c086a6d855"},
|
{file = "httptools-0.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5e3088f4ed33947e16fd865b8200f9cfae1144f41b64a8cf19b599508e096bc"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9b90bf58f3ba04e60321a23a8723a1ff2a9377502535e70495e5ada8e6e6722"},
|
{file = "httptools-0.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c2a56b6aad7cc8f5551d8e04ff5a319d203f9d870398b94702300de50190f63"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a99346ebcb801b213c591540837340bdf6fd060a8687518d01c607d338b7424"},
|
{file = "httptools-0.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b571b281a19762adb3f48a7731f6842f920fa71108aff9be49888320ac3e24d"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:645373c070080e632480a3d251d892cb795be3d3a15f86975d0f1aca56fd230d"},
|
{file = "httptools-0.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa47ffcf70ba6f7848349b8a6f9b481ee0f7637931d91a9860a1838bfc586901"},
|
||||||
{file = "httptools-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:34d2903dd2a3dd85d33705b6fde40bf91fc44411661283763fd0746723963c83"},
|
{file = "httptools-0.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:bede7ee075e54b9a5bde695b4fc8f569f30185891796b2e4e09e2226801d09bd"},
|
||||||
{file = "httptools-0.4.0.tar.gz", hash = "sha256:2c9a930c378b3d15d6b695fb95ebcff81a7395b4f9775c4f10a076beb0b2c1ff"},
|
{file = "httptools-0.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:64eba6f168803a7469866a9c9b5263a7463fa8b7a25b35e547492aa7322036b6"},
|
||||||
|
{file = "httptools-0.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4b098e4bb1174096a93f48f6193e7d9aa7071506a5877da09a783509ca5fff42"},
|
||||||
|
{file = "httptools-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9423a2de923820c7e82e18980b937893f4aa8251c43684fa1772e341f6e06887"},
|
||||||
|
{file = "httptools-0.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca1b7becf7d9d3ccdbb2f038f665c0f4857e08e1d8481cbcc1a86a0afcfb62b2"},
|
||||||
|
{file = "httptools-0.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:50d4613025f15f4b11f1c54bbed4761c0020f7f921b95143ad6d58c151198142"},
|
||||||
|
{file = "httptools-0.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8ffce9d81c825ac1deaa13bc9694c0562e2840a48ba21cfc9f3b4c922c16f372"},
|
||||||
|
{file = "httptools-0.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:1af91b3650ce518d226466f30bbba5b6376dbd3ddb1b2be8b0658c6799dd450b"},
|
||||||
|
{file = "httptools-0.5.0.tar.gz", hash = "sha256:295874861c173f9101960bba332429bb77ed4dcd8cdf5cee9922eb00e4f6bc09"},
|
||||||
]
|
]
|
||||||
httpx = [
|
httpx = [
|
||||||
{file = "httpx-0.23.0-py3-none-any.whl", hash = "sha256:42974f577483e1e932c3cdc3cd2303e883cbfba17fe228b0f63589764d7b9c4b"},
|
{file = "httpx-0.23.0-py3-none-any.whl", hash = "sha256:42974f577483e1e932c3cdc3cd2303e883cbfba17fe228b0f63589764d7b9c4b"},
|
||||||
{file = "httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"},
|
{file = "httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"},
|
||||||
]
|
]
|
||||||
idna = [
|
idna = [
|
||||||
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
|
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
|
||||||
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
|
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||||
]
|
]
|
||||||
itsdangerous = [
|
itsdangerous = [
|
||||||
{file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
|
{file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
|
||||||
@@ -558,47 +606,120 @@ MarkupSafe = [
|
|||||||
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
|
||||||
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
|
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
|
||||||
]
|
]
|
||||||
|
motor = [
|
||||||
|
{file = "motor-3.0.0-py3-none-any.whl", hash = "sha256:b076de44970f518177f0eeeda8b183f52eafa557775bfe3294e93bda18867a71"},
|
||||||
|
{file = "motor-3.0.0.tar.gz", hash = "sha256:3e36d29406c151b61342e6a8fa5e90c00c4723b76e30f11276a4373ea2064b7d"},
|
||||||
|
]
|
||||||
pycparser = [
|
pycparser = [
|
||||||
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
|
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
|
||||||
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
|
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
|
||||||
]
|
]
|
||||||
pydantic = [
|
pydantic = [
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:221166d99726238f71adc4fa9f3e94063a10787574b966f86a774559e709ac5a"},
|
{file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"},
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a90e85d95fd968cd7cae122e0d3e0e1f6613bc88c1ff3fe838ac9785ea4b1c4c"},
|
{file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"},
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2157aaf5718c648eaec9e654a34179ae42ffc363dc3ad058538a4f3ecbd9341"},
|
{file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"},
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6142246fc9adb51cadaeb84fb52a86f3adad4c6a7b0938a5dd0b1356b0088217"},
|
{file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"},
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:60dad97a09b6f44690c05467a4f397b62bfc2c839ac39102819d6979abc2be0d"},
|
{file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"},
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d6f5bcb59d33ec46621dae76e714c53035087666cac80c81c9047a84f3ff93d0"},
|
{file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"},
|
||||||
{file = "pydantic-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:522906820cd60e63c7960ba83078bf2d2ad2dd0870bf68248039bcb1ec3eb0a4"},
|
{file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d545c89d88bdd5559db17aeb5a61a26799903e4bd76114779b3bf1456690f6ce"},
|
{file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ad2374b5b3b771dcc6e2f6e0d56632ab63b90e9808b7a73ad865397fcdb4b2cd"},
|
{file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90e02f61b7354ed330f294a437d0bffac9e21a5d46cb4cc3c89d220e497db7ac"},
|
{file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc5ffe7bd0b4778fa5b7a5f825c52d6cfea3ae2d9b52b05b9b1d97e36dee23a8"},
|
{file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7acb7b66ffd2bc046eaff0063df84c83fc3826722d5272adaeadf6252e17f691"},
|
{file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7e6786ed5faa559dea5a77f6d2de9a08d18130de9344533535d945f34bdcd42e"},
|
{file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"},
|
||||||
{file = "pydantic-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:c7bf8ff1d18186eb0cbe42bd9bfb4cbf7fde1fd01b8608925458990c21f202f0"},
|
{file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"},
|
||||||
{file = "pydantic-1.10.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:14a5babda137a294df7ad5f220986d79bbb87fdeb332c6ded61ce19da7f5f3bf"},
|
{file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"},
|
||||||
{file = "pydantic-1.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5659cb9c6b3d27fc0067025c4f5a205f5e838232a4a929b412781117c2343d44"},
|
{file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"},
|
||||||
{file = "pydantic-1.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8d70fb91b03c32d2e857b071a22a5225e6b625ca82bd2cc8dd729d88e0bd200"},
|
{file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"},
|
||||||
{file = "pydantic-1.10.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9a93be313e40f12c6f2cb84533b226bbe23d0774872e38d83415e6890215e3a6"},
|
{file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"},
|
||||||
{file = "pydantic-1.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d55aeb01bb7bd7c7e1bd904668a4a2ffcbb1c248e7ae9eb40a272fd7e67dd98b"},
|
{file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"},
|
||||||
{file = "pydantic-1.10.1-cp37-cp37m-win_amd64.whl", hash = "sha256:43d41b6f13706488e854729955ba8f740e6ec375cd16b72b81dc24b9d84f0d15"},
|
{file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f31ffe0e38805a0e6410330f78147bb89193b136d7a5f79cae60d3e849b520a6"},
|
{file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8eee69eda7674977b079a21e7bf825b59d8bf15145300e8034ed3eb239ac444f"},
|
{file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f927bff6c319fc92e0a2cbeb2609b5c1cd562862f4b54ec905e353282b7c8b1"},
|
{file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb1bc3f8fef6ba36977108505e90558911e7fbccb4e930805d5dd90891b56ff4"},
|
{file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96ab6ce1346d14c6e581a69c333bdd1b492df9cf85ad31ad77a8aa42180b7e09"},
|
{file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:444cf220a12134da1cd42fe4f45edff622139e10177ce3d8ef2b4f41db1291b2"},
|
{file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"},
|
||||||
{file = "pydantic-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:dbfbff83565b4514dd8cebc8b8c81a12247e89427ff997ad0a9da7b2b1065c12"},
|
{file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5327406f4bfd5aee784e7ad2a6a5fdd7171c19905bf34cb1994a1ba73a87c468"},
|
{file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1072eae28bf034a311764c130784e8065201a90edbca10f495c906737b3bd642"},
|
{file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce901335667a68dfbc10dd2ee6c0d676b89210d754441c2469fbc37baf7ee2ed"},
|
{file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54d6465cd2112441305faf5143a491b40de07a203116b5755a2108e36b25308d"},
|
{file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2b5e5e7a0ec96704099e271911a1049321ba1afda92920df0769898a7e9a1298"},
|
{file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ae43704358304da45c1c3dd7056f173c618b252f91594bcb6d6f6b4c6c284dee"},
|
{file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"},
|
||||||
{file = "pydantic-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:2d7da49229ffb1049779a5a6c1c50a26da164bd053cf8ee9042197dc08a98259"},
|
{file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"},
|
||||||
{file = "pydantic-1.10.1-py3-none-any.whl", hash = "sha256:f8b10e59c035ff3dcc9791619d6e6c5141e0fa5cbe264e19e267b8d523b210bf"},
|
{file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"},
|
||||||
{file = "pydantic-1.10.1.tar.gz", hash = "sha256:d41bb80347a8a2d51fbd6f1748b42aca14541315878447ba159617544712f770"},
|
{file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"},
|
||||||
|
]
|
||||||
|
pymongo = [
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:b9e4981a65f8500a3a46bb3a1e81b9feb45cf0b2115ad9c4f8d517326d026940"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1c81414b706627f15e921e29ae2403aab52e33e36ed92ed989c602888d7c3b90"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux1_i686.whl", hash = "sha256:c549bb519456ee230e92f415c5b4d962094caac0fdbcc4ed22b576f66169764e"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:70216ec4c248213ae95ea499b6314c385ce01a5946c448fb22f6c8395806e740"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:8a86e8c2ac2ec87141e1c6cb00bdb18a4560f06e5f96769abcd1dda24dc0e764"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:314b556afd72eb21a6a10bd1f45ef252509f014f80207db59c97372103c88237"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:902e2c9030cb042c49750bc70d72d830d42c64ea0df5ff8630c171e065c93dd7"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:c69ef5906dcd6ec565d4d887ba97ceb2a84f3b614307ee3b4780cb1ea40b1867"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07564178ecc203a84f63e72972691af6c0c82d2dc0c9da66ba711695276089ba"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47d5f10922cf7f7dfcd1406bd0926cef6d866a75953c3745502dffd7ac197dd"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cadaaa5c19ad23fc84559e90284f2eb003c36958ebb2c06f286b678f441285f"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d94f535df9f539615bc3dbbef185ded3b609373bb44ca1afffcabac70202678a"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:147a23cd96feb67606ac957744d8d25b013426cdc3c7164a4f99bd8253f649e3"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-win32.whl", hash = "sha256:ecdcb0d4e9b08b739035f57a09330efc6f464bd7f942b63897395d996ca6ebd5"},
|
||||||
|
{file = "pymongo-4.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:8c223aea52c359cc8fdee5bd3475532590755c269ec4d4fe581acd47a44e9952"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:fe0820d169635e41c14a5d21514282e0b93347878666ec9d5d3bf0eed0649948"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e39cacee70a98758f9b2da53ee175378f07c60113b1fa4fae40cbaee5583181e"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:701d331060dae72bf3ebdb82924405d14136a69282ccb00c89fc69dee21340b4"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e08fe1731f5429435b8dea1db9663f9ed1812915ff803fc9991c7c4841ed62ad"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:60c470a58c5b62b1b12a5f5458f8e2f2f67b94e198d03dc5352f854d9230c394"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:b211e161b6cc2790e0d640ad38e0429d06c944e5da23410f4dc61809dba25095"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:ed90a9de4431cbfb2f3b2ef0c5fd356e61c85117b2be4db3eae28cb409f6e2d5"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:68e1e49a5675748233f7b05330f092582cd52f2850b4244939fd75ba640593ed"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:764fc15418d94bce5c2f8ebdbf66544f96f42efb1364b61e715e5b33281b388d"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e64442aba81ed4df1ca494b87bf818569a1280acaa73071c68014f7a884e83f1"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83168126ae2457d1a19b2af665cafa7ef78c2dcff192d7d7b5dad6b36c73ae24"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69d0180bca594e81cdb4a2af328bdb4046f59e10aaeef7619496fe64f2ec918c"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80cbf0b043061451660099fff9001a7faacb2c9c983842b4819526e2f944dc6c"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e1b8f5e2f9637492b0da4d51f78ecb17786e61d6c461ead8542c944750faf4f9"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1a957cdc2b26eeed4d8f1889a40c6023dd1bd94672dd0f5ce327314f2caaefd4"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-win32.whl", hash = "sha256:6bd5888997ea3eae9830c6cc7964b61dcfbc50eb3a5a6ce56ad5f86d5579b11c"},
|
||||||
|
{file = "pymongo-4.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dc24737d24ce0de762bee9c2a884639819485f679bbac8ab5be9c161ef6f9b2c"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:193cc97d44b1e6d2253ea94e30c6f94f994efb7166e2452af4df55825266e88b"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e152c26ffc30331e9d57591fc4c05453c209aa20ba299d1deb7173f7d1958c22"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8a9bc4dcfc2bda69ee88cdb7a89b03f2b8eca668519b704384a264dea2db4209"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8cbb868e88c4eee1c53364bb343d226a3c0e959e791e6828030cb78f46cfcbe3"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:2bfe6b59f431f40fa545547616f4acf0c0c4b64518b1f951083e3bad06eb368b"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:ff66014687598823b6b23751884b4aa67eb934445406d95894dfc60cb7bfcc18"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:31c50da4a080166bc29403aa91f4c76e0889b4f24928d1b60508a37c1bf87f9a"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ccfdc7722df445c49dc6b5d514c3544cad99b53189165f7546793933050ac7fb"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc7ebc37b03956a070260665079665eae69e5e96007694214f3a2107af96816a"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8b4a782aac43948308087b962c9ecb030ba98886ce6dee3ad7aafe8c5e1ce80"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1c23527f8e13f526fededbb96f2e7888f179fe27c51d41c2724f7059b75b2fa"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cc3c35aeeceb67143914db67f685206e1aa37ea837d872f4bc28d7f80917c9"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e09cdf5aad507c8faa30d97884cc42932ed3a9c2b7f22cc3ccc607bae03981b3"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0f53253f4777cbccc426e669a2af875f26c95bd090d88593287b9a0a8ac7fa25"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21238b19243a42f9a34a6d39e7580ceebc6da6d2f3cf729c1cff9023cb61a5f1"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-win32.whl", hash = "sha256:766acb5b1a19eae0f7467bcd3398748f110ea5309cdfc59faa5185dcc7fd4dca"},
|
||||||
|
{file = "pymongo-4.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:10f09c4f09757c2e2a707ad7304f5d69cb8fdf7cbfb644dbacfe5bbe8afe311b"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6bf01b9237f794fa3bdad5089474067d28be7e199b356a18d3f247a45775f26"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d8bb745321716e7a11220a67c88212ecedde4021e1de4802e563baef9df921d2"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3be53e9888e759c49ae35d747ff77a04ff82b894dd64601e0f3a5a159b406245"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a3efdf154844244e0dabe902cf1827fdced55fa5b144adec2a86e5ce50a99b97"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:a7eb5b06744b911b6668b427c8abc71b6d624e72d3dfffed00988fa1b4340f97"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:b0be613d926c5dbb0d3fc6b58e4f2be4979f80ae76fda6e47309f011b388fe0c"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:e7dcb73f683c155885a3488646fcead3a895765fed16e93c9b80000bc69e96cb"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:b537dd282de1b53d9ae7cf9f3df36420c8618390f2da92100391f3ba8f3c141a"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d98d2a8283c9928a9e5adf2f3c0181e095579e9732e1613aaa55d386e2bcb6c5"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76892bbce743eb9f90360b3626ea92f13d338010a1004b4488e79e555b339921"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:124d0e880b66f9b0778613198e89984984fdd37a3030a9007e5f459a42dfa2d3"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:773467d25c293f8e981b092361dab5fd800e1ba318403b7959d35004c67faedc"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6673ab3fbf3135cc1a8c0f70d480db5b2378c3a70af8d602f73f76b8338bdf97"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:153b8f8705970756226dfeeb7bb9637e0ad54a4d79b480b4c8244e34e16e1662"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:01721da74558f2f64a9f162ee063df403ed656b7d84229268d8e4ae99cfba59c"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-win32.whl", hash = "sha256:a25c0eb2d610b20e276e684be61c337396813b636b69373c17314283cb1a3b14"},
|
||||||
|
{file = "pymongo-4.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:44b36ccb90aac5ea50be23c1a6e8f24fbfc78afabdef114af16c6e0a80981364"},
|
||||||
|
{file = "pymongo-4.2.0.tar.gz", hash = "sha256:72f338f6aabd37d343bd9d1fdd3de921104d395766bcc5cdc4039e4c2dd97766"},
|
||||||
]
|
]
|
||||||
python-dotenv = [
|
python-dotenv = [
|
||||||
{file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"},
|
{file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"},
|
||||||
@@ -660,42 +781,56 @@ uvicorn = [
|
|||||||
{file = "uvicorn-0.18.3.tar.gz", hash = "sha256:9a66e7c42a2a95222f76ec24a4b754c158261c4696e683b9dadc72b590e0311b"},
|
{file = "uvicorn-0.18.3.tar.gz", hash = "sha256:9a66e7c42a2a95222f76ec24a4b754c158261c4696e683b9dadc72b590e0311b"},
|
||||||
]
|
]
|
||||||
uvloop = [
|
uvloop = [
|
||||||
{file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"},
|
{file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718"},
|
||||||
{file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"},
|
{file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c"},
|
||||||
{file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"},
|
{file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d"},
|
||||||
{file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"},
|
{file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024"},
|
||||||
{file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"},
|
{file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa"},
|
||||||
{file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"},
|
{file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811"},
|
||||||
{file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"},
|
{file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c"},
|
||||||
{file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"},
|
{file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e"},
|
||||||
{file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"},
|
{file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539"},
|
||||||
{file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"},
|
{file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4"},
|
||||||
{file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"},
|
{file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05"},
|
||||||
{file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"},
|
{file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376"},
|
||||||
{file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"},
|
{file = "uvloop-0.17.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b"},
|
||||||
{file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"},
|
{file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8"},
|
||||||
{file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"},
|
{file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62"},
|
||||||
{file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"},
|
{file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d"},
|
||||||
|
{file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667"},
|
||||||
|
{file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738"},
|
||||||
|
{file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20"},
|
||||||
|
{file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f"},
|
||||||
|
{file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595"},
|
||||||
|
{file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578"},
|
||||||
|
{file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474"},
|
||||||
|
{file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b"},
|
||||||
|
{file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c"},
|
||||||
|
{file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8"},
|
||||||
|
{file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c"},
|
||||||
|
{file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9"},
|
||||||
|
{file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded"},
|
||||||
|
{file = "uvloop-0.17.0.tar.gz", hash = "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1"},
|
||||||
]
|
]
|
||||||
watchfiles = [
|
watchfiles = [
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:1e41c8b4bf3e07c18aa51775b36b718830fa727929529a7d6e5b38cf845a06b4"},
|
{file = "watchfiles-0.17.0-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:c7e1ffbd03cbcb46d1b7833e10e7d6b678ab083b4e4b80db06cfff5baca3c93f"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:b2c7ad91a867dd688b9a12097dd6a4f89397b43fccee871152aa67197cc94398"},
|
{file = "watchfiles-0.17.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:539bcdb55a487126776c9d8c011094214d1df3f9a2321a6c0b1583197309405a"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:75a4b9cec1b1c337ea77d4428b29861553d6bf8179923b1bc7e825e217460e2c"},
|
{file = "watchfiles-0.17.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:00e5f307a58752ec1478eeb738863544bde21cc7a2728bd1c216060406bde9c1"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a3debb19912072799d7ca53e99fc5f090f77948f5601392623b2a416b4c86be"},
|
{file = "watchfiles-0.17.0-cp37-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:92675f379a9d5adbc6a52179f3e39aa56944c6eecb80384608fff2ed2619103a"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35f3e411822e14a35f2ef656535aad4e6e79670d6b6ef8e53db958e28916b1fe"},
|
{file = "watchfiles-0.17.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1dd1e3181ad5d83ca35e9147c72e24f39437fcdf570c9cdc532016399fb62957"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9a7a6dc63684ff5ba11f0be0e64f744112c3c7a0baf4ec8f6794f9a6257d21e"},
|
{file = "watchfiles-0.17.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:204950f1d6083539af5c8b7d4f5f8039c3ce36fa692da12d9743448f3199cb15"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e939a2693404ac11e055f9d1237db8ad7635e2185a6143bde00116e691ea2983"},
|
{file = "watchfiles-0.17.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:4056398d8f6d4972fe0918707b59d4cb84470c91d3c37f0e11e5a66c2a598760"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cd7d2fd9a8f28066edc8db5278f3632eb94d10596af760fa0601631f32b1a41e"},
|
{file = "watchfiles-0.17.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ffff3418dc753a2aed2d00200a4daeaac295c40458f8012836a65555f288be8b"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-win32.whl", hash = "sha256:f91035a273001390093a09e52274a34695b0d15ee8736183b640bbc3b8a432ab"},
|
{file = "watchfiles-0.17.0-cp37-abi3-win32.whl", hash = "sha256:b5c334cd3bc88aa4a8a1e08ec9f702b63c947211275defdc2dd79dc037fcb500"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-win_amd64.whl", hash = "sha256:a8a1809bf910672aa0b7ed6e6045d4fc2cf1e0718b99bc443ef17faa5697b68a"},
|
{file = "watchfiles-0.17.0-cp37-abi3-win_amd64.whl", hash = "sha256:53a2faeb121bc51bb6b960984f46901227e2e2475acc5a8d4c905a600436752d"},
|
||||||
{file = "watchfiles-0.16.1-cp37-abi3-win_arm64.whl", hash = "sha256:baa6d0c1c5140e1dcf6ff802dd7b09fcd95b358e50d42fabc83d83f719451c54"},
|
{file = "watchfiles-0.17.0-cp37-abi3-win_arm64.whl", hash = "sha256:58dc3140dcf02a8aa76464a77a093016f10e89306fec21a4814922a64f3e8b9f"},
|
||||||
{file = "watchfiles-0.16.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5741246ae399a03395aa5ee35480083a4f29d58ffd41dd3395594f8805f8cdbc"},
|
{file = "watchfiles-0.17.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:adcf15ecc2182ea9d2358c1a8c2b53203c3909484918776929b7bbe205522c0e"},
|
||||||
{file = "watchfiles-0.16.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:44c6aff58b8a70a26431737e483a54e8e224279b21873388571ed184fe7c91a7"},
|
{file = "watchfiles-0.17.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:afd35a1bd3b9e68efe384ae7538481ae725597feb66f56f4bd23ecdbda726da0"},
|
||||||
{file = "watchfiles-0.16.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d1b2d0cf060e5222a930a3e2f40f6577da1d18c085c32741b98a128dc1e72c"},
|
{file = "watchfiles-0.17.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad2bdcae4c0f07ca6c090f5a2c30188cc6edba011b45e7c96eb1896648092367"},
|
||||||
{file = "watchfiles-0.16.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:70159e759f52b65a50c498182dece80364bfd721e839c254c328cbc7a1716616"},
|
{file = "watchfiles-0.17.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:a53cb6c06e5c1f216c792fbb432ce315239d432cb8b68d508547100939ec0399"},
|
||||||
{file = "watchfiles-0.16.1-pp39-pypy39_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22af3b915f928ef59d427d7228668f87ac8054ed8200808c73fbcaa4f82d5572"},
|
{file = "watchfiles-0.17.0-pp39-pypy39_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6a3d6c699f3ce238dfa90bcef501f331a69b0d9b076f14459ed8eab26ba2f4cf"},
|
||||||
{file = "watchfiles-0.16.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a6a1ac96edf5bc3f8e36f4462fc1daad0ec3769ff2adb920571e120e37c91c5"},
|
{file = "watchfiles-0.17.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7f4271af86569bdbf131dd5c7c121c45d0ed194f3c88b88326e48a3b6a2db12"},
|
||||||
{file = "watchfiles-0.16.1.tar.gz", hash = "sha256:aed7575e24434c8fec2f2bbb0cecb1521ea1240234d9108db7915a3424d92394"},
|
{file = "watchfiles-0.17.0.tar.gz", hash = "sha256:ae7c57ef920589a40270d5ef3216d693f4e6f8864d8fc8b6cb7885ca98ad2a61"},
|
||||||
]
|
]
|
||||||
websockets = [
|
websockets = [
|
||||||
{file = "websockets-10.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978"},
|
{file = "websockets-10.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978"},
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ Authlib = "^1.0.1"
|
|||||||
httpx = "^0.23.0"
|
httpx = "^0.23.0"
|
||||||
itsdangerous = "^2.1.2"
|
itsdangerous = "^2.1.2"
|
||||||
Jinja2 = "^3.1.2"
|
Jinja2 = "^3.1.2"
|
||||||
|
motor = "^3.0.0"
|
||||||
|
cryptography = "^38.0.1"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
GITEA_CLIENT_ID="12345678-abcd-1234-efgh-1234567890ab"
|
GITEA_CLIENT_ID="12345678-abcd-1234-efgh-1234567890ab"
|
||||||
GITEA_CLIENT_SECRET="gto_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
GITEA_CLIENT_SECRET="gto_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
SESSION_SECRET_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
SESSION_SECRET_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
FERNET_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
@@ -1,34 +1,71 @@
|
|||||||
|
import asyncio
|
||||||
import json
|
import json
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.responses import HTMLResponse
|
from fastapi.staticfiles import StaticFiles
|
||||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
from fastapi.responses import HTMLResponse, PlainTextResponse
|
||||||
|
from starlette.middleware.sessions import SessionMiddleware
|
||||||
|
|
||||||
from .settings import settings
|
from .settings import settings
|
||||||
from .user import user_auth
|
from .auth import user_auth, config as auth_config
|
||||||
|
from .map_tiles import map_tiles, map_meta
|
||||||
|
from .templates import j2env
|
||||||
|
from .monitoring import monitoring, ws_manager
|
||||||
|
from .api import api
|
||||||
|
from . import db
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
app.add_middleware(SessionMiddleware, secret_key=auth_config.get("SESSION_SECRET_KEY"))
|
||||||
|
|
||||||
app.mount("/user/", user_auth)
|
app.mount("/user/", user_auth)
|
||||||
|
app.mount("/map/", map_meta)
|
||||||
|
app.mount("/tiles/", map_tiles)
|
||||||
|
app.mount("/ipmi/", monitoring)
|
||||||
|
app.mount("/api/", api)
|
||||||
|
|
||||||
|
|
||||||
|
def render_lua_installer():
|
||||||
|
with open(f"{settings.lua_out_path}/manifest.txt", "r") as f:
|
||||||
|
file_list = [name.strip() for name in f.readlines()]
|
||||||
|
return j2env.get_template("install.lua").render(
|
||||||
|
deploy_path=settings.deploy_path, file_list=file_list
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
installer = render_lua_installer()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/install")
|
||||||
|
async def get_installer():
|
||||||
|
if settings.dev_mode:
|
||||||
|
installer = render_lua_installer()
|
||||||
|
return PlainTextResponse(installer)
|
||||||
|
|
||||||
|
|
||||||
|
app.mount("/lua/", StaticFiles(directory=settings.lua_out_path))
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_event("startup")
|
||||||
|
async def on_startup():
|
||||||
|
await db.on_startup()
|
||||||
|
asyncio.get_running_loop().create_task(ws_manager.queue_task())
|
||||||
|
|
||||||
|
|
||||||
|
frontend = FastAPI()
|
||||||
|
|
||||||
manifest = dict()
|
manifest = dict()
|
||||||
if not settings.dev_mode:
|
if not settings.dev_mode:
|
||||||
from fastapi.staticfiles import StaticFiles
|
|
||||||
|
|
||||||
with open(f"{settings.frontend_path}/manifest.json", "r") as f:
|
with open(f"{settings.frontend_path}/manifest.json", "r") as f:
|
||||||
manifest = json.load(f)
|
manifest = json.load(f)
|
||||||
|
|
||||||
|
|
||||||
j2env = Environment(
|
|
||||||
loader=FileSystemLoader("templates"),
|
|
||||||
autoescape=select_autoescape(),
|
|
||||||
)
|
|
||||||
index = j2env.get_template("index.html").render(
|
index = j2env.get_template("index.html").render(
|
||||||
dev_mode=settings.dev_mode,
|
dev_mode=settings.dev_mode,
|
||||||
manifest=manifest,
|
manifest=manifest,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.middleware("http")
|
@frontend.middleware("http")
|
||||||
async def index_catch_all(request: Request, call_next):
|
async def index_catch_all(request: Request, call_next):
|
||||||
response = await call_next(request)
|
response = await call_next(request)
|
||||||
|
|
||||||
@@ -39,4 +76,6 @@ async def index_catch_all(request: Request, call_next):
|
|||||||
|
|
||||||
|
|
||||||
if not settings.dev_mode:
|
if not settings.dev_mode:
|
||||||
app.mount("/", StaticFiles(directory=settings.frontend_path))
|
frontend.mount("/", StaticFiles(directory=settings.frontend_path))
|
||||||
|
|
||||||
|
app.mount("/", frontend)
|
||||||
|
|||||||
82
server/server/api.py
Normal file
82
server/server/api.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
from typing import Any
|
||||||
|
from bson import ObjectId
|
||||||
|
|
||||||
|
from fastapi import Body, FastAPI, HTTPException, Request, status, Depends
|
||||||
|
from fastapi.responses import PlainTextResponse
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
import pymongo
|
||||||
|
|
||||||
|
from .db import events, PyObjectId, create_event, computers, open_token, close_token
|
||||||
|
from .auth import get_user, generate_token, decrypt_token
|
||||||
|
from .settings import settings
|
||||||
|
from .templates import j2env
|
||||||
|
|
||||||
|
api = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class Event(BaseModel):
|
||||||
|
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
|
||||||
|
timestamp: datetime
|
||||||
|
type: str
|
||||||
|
value: Any
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
json_encoders = {ObjectId: str}
|
||||||
|
|
||||||
|
|
||||||
|
@api.get("/events", response_model=list[Event])
|
||||||
|
async def get_events():
|
||||||
|
return await events.find().sort("timestamp", pymongo.DESCENDING).to_list(None)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
@api.get("/events/{id}", response_model=Event)
|
||||||
|
async def get_single_event(id: PyObjectId):
|
||||||
|
if (event := await events.find_one({"_id": id})) is not None:
|
||||||
|
return event
|
||||||
|
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO auth
|
||||||
|
@api.post("/events", response_model=Event, status_code=status.HTTP_201_CREATED)
|
||||||
|
async def push_event(value: Any = Body(...)):
|
||||||
|
return await create_event(value)
|
||||||
|
|
||||||
|
|
||||||
|
# Computer registration
|
||||||
|
|
||||||
|
|
||||||
|
@api.get("/create-registration-token")
|
||||||
|
async def generate_registration_token(user=Depends(get_user)):
|
||||||
|
token = generate_token({})
|
||||||
|
await open_token(token)
|
||||||
|
await create_event("registration_create", user=user, token=token)
|
||||||
|
return token
|
||||||
|
|
||||||
|
|
||||||
|
id_template = j2env.get_template("auth.lua")
|
||||||
|
|
||||||
|
|
||||||
|
@api.get("/issue-id/{reg_token}")
|
||||||
|
async def issue_computer_id(request: Request, reg_token: str):
|
||||||
|
try:
|
||||||
|
token = decrypt_token(reg_token)
|
||||||
|
assert await close_token(reg_token) == 1
|
||||||
|
except Exception as e:
|
||||||
|
await create_event("registration_fail", token=reg_token, exception=repr(e))
|
||||||
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
|
||||||
|
new_computer = await computers.insert_one({})
|
||||||
|
inserted_id = new_computer.inserted_id
|
||||||
|
token = generate_token({"for": str(inserted_id)})
|
||||||
|
|
||||||
|
await create_event("registration_use", token=reg_token, computer=inserted_id)
|
||||||
|
|
||||||
|
return PlainTextResponse(
|
||||||
|
id_template.render(
|
||||||
|
{"id": inserted_id, "token": token, "server": settings.deploy_path}
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
from fastapi import FastAPI, Request
|
import base64
|
||||||
|
import json
|
||||||
|
|
||||||
|
from fastapi import FastAPI, HTTPException, Header, Request, status
|
||||||
from pydantic import BaseModel, HttpUrl
|
from pydantic import BaseModel, HttpUrl
|
||||||
from starlette.config import Config
|
from starlette.config import Config
|
||||||
from starlette.middleware.sessions import SessionMiddleware
|
|
||||||
from starlette.responses import HTMLResponse, RedirectResponse
|
from starlette.responses import HTMLResponse, RedirectResponse
|
||||||
from authlib.integrations.starlette_client import OAuth, OAuthError
|
from authlib.integrations.starlette_client import OAuth, OAuthError
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
|
|
||||||
config = Config("secret.env") # TODO unify this with settings
|
config = Config("secret.env") # TODO unify this with settings
|
||||||
|
|
||||||
@@ -13,8 +16,23 @@ oauth.register(
|
|||||||
server_metadata_url="https://git.leafbla.de/.well-known/openid-configuration",
|
server_metadata_url="https://git.leafbla.de/.well-known/openid-configuration",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fernet = Fernet(config.get("FERNET_KEY"))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_token(data: any) -> str:
|
||||||
|
return base64.urlsafe_b64encode(fernet.encrypt(json.dumps(data).encode())).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt_token(b64: str, ttl: int = 300):
|
||||||
|
try:
|
||||||
|
token = base64.urlsafe_b64decode(b64)
|
||||||
|
data = fernet.decrypt(token, ttl)
|
||||||
|
return json.loads(data.decode())
|
||||||
|
except Exception as _:
|
||||||
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
|
||||||
|
|
||||||
user_auth = FastAPI()
|
user_auth = FastAPI()
|
||||||
user_auth.add_middleware(SessionMiddleware, secret_key=config.get("SESSION_SECRET_KEY"))
|
|
||||||
|
|
||||||
|
|
||||||
@user_auth.get("/login")
|
@user_auth.get("/login")
|
||||||
@@ -76,3 +94,22 @@ async def display_current_user(request: Request):
|
|||||||
return MeResponse(
|
return MeResponse(
|
||||||
name=user["preferred_username"], email=user["email"], picture=user["picture"]
|
name=user["preferred_username"], email=user["email"], picture=user["picture"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_user(request: Request):
|
||||||
|
user = request.session.get("user")
|
||||||
|
if user is None:
|
||||||
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
async def validate_computer(id: str, authorization=Header()):
|
||||||
|
match authorization.split():
|
||||||
|
case ["Bearer", token]:
|
||||||
|
data = decrypt_token(token, ttl=None)
|
||||||
|
if "for" in data and data["for"] == id:
|
||||||
|
return id
|
||||||
|
case _:
|
||||||
|
pass
|
||||||
|
|
||||||
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||||
57
server/server/db.py
Normal file
57
server/server/db.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from bson import ObjectId
|
||||||
|
import motor.motor_asyncio as motor
|
||||||
|
from .settings import settings
|
||||||
|
|
||||||
|
client: motor.AsyncIOMotorClient = motor.AsyncIOMotorClient(settings.mongo_uri)
|
||||||
|
|
||||||
|
db = client["controlpanel"]
|
||||||
|
events: motor.AsyncIOMotorCollection = db["events"]
|
||||||
|
|
||||||
|
|
||||||
|
async def create_event(type: str, **kwargs: any):
|
||||||
|
event = {
|
||||||
|
"timestamp": datetime.now(),
|
||||||
|
"type": type,
|
||||||
|
"value": kwargs,
|
||||||
|
}
|
||||||
|
new_event = await events.insert_one(event)
|
||||||
|
created_event = await events.find_one({"_id": new_event.inserted_id})
|
||||||
|
return created_event
|
||||||
|
|
||||||
|
|
||||||
|
computers = db["computers"]
|
||||||
|
|
||||||
|
open_tokens = db["open_tokens"]
|
||||||
|
|
||||||
|
|
||||||
|
async def on_startup():
|
||||||
|
await open_tokens.create_index("timestamp", expireAfterSeconds=300)
|
||||||
|
if not settings.dev_mode:
|
||||||
|
await create_event("server_start")
|
||||||
|
|
||||||
|
|
||||||
|
async def open_token(token: str):
|
||||||
|
await open_tokens.insert_one({"timestamp": datetime.now(), "token": token})
|
||||||
|
|
||||||
|
|
||||||
|
async def close_token(token: str):
|
||||||
|
deleted = await open_tokens.delete_one({"token": token})
|
||||||
|
return deleted.deleted_count
|
||||||
|
|
||||||
|
|
||||||
|
class PyObjectId(ObjectId):
|
||||||
|
@classmethod
|
||||||
|
def __get_validators__(cls):
|
||||||
|
yield cls.validate
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(cls, v):
|
||||||
|
if not ObjectId.is_valid(v):
|
||||||
|
raise ValueError("Invalid objectid")
|
||||||
|
return ObjectId(v)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __modify_schema__(cls, field_schema):
|
||||||
|
field_schema.update(type="string")
|
||||||
48
server/server/map_tiles.py
Normal file
48
server/server/map_tiles.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from fastapi import FastAPI, Response
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
|
from .settings import settings
|
||||||
|
from .templates import j2env
|
||||||
|
|
||||||
|
map_tiles = StaticFiles(directory=f"{settings.unmined_out_path}/tiles")
|
||||||
|
|
||||||
|
map_meta = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class JsResponse(Response):
|
||||||
|
media_type = "text/javascript"
|
||||||
|
|
||||||
|
|
||||||
|
MAP_PROPS_FILE = f"{settings.unmined_out_path}/unmined.map.properties.js"
|
||||||
|
MAP_REGIONS_FILE = f"{settings.unmined_out_path}/unmined.map.regions.js"
|
||||||
|
UNMINED_FILE = f"{settings.unmined_out_path}/unmined.openlayers.js"
|
||||||
|
|
||||||
|
with open(UNMINED_FILE, "r") as f:
|
||||||
|
unmined_script = j2env.get_template("unmined.js").render(
|
||||||
|
unmined_file=UNMINED_FILE, unmined_script=f.read()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_metadata():
|
||||||
|
with open(MAP_PROPS_FILE, "r") as f:
|
||||||
|
map_props = f.read()
|
||||||
|
with open(MAP_REGIONS_FILE, "r") as f:
|
||||||
|
map_regions = f.read()
|
||||||
|
|
||||||
|
return j2env.get_template("metadata.js").render(
|
||||||
|
props_file=MAP_PROPS_FILE,
|
||||||
|
map_props=map_props,
|
||||||
|
regions_file=MAP_REGIONS_FILE,
|
||||||
|
map_regions=map_regions,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@map_meta.get("/unmined.js", response_class=JsResponse)
|
||||||
|
async def get_unmined():
|
||||||
|
return unmined_script
|
||||||
|
|
||||||
|
|
||||||
|
@map_meta.get("/metadata.js", response_class=JsResponse)
|
||||||
|
async def get_metadata():
|
||||||
|
# TODO cache
|
||||||
|
return parse_metadata()
|
||||||
130
server/server/monitoring.py
Normal file
130
server/server/monitoring.py
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import asyncio
|
||||||
|
from typing import Any
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends
|
||||||
|
from pydantic import BaseModel, ValidationError
|
||||||
|
|
||||||
|
from .db import create_event
|
||||||
|
from .auth import validate_computer
|
||||||
|
|
||||||
|
monitoring = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenContent(BaseModel):
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
width: int
|
||||||
|
height: int
|
||||||
|
blink: bool
|
||||||
|
fg: int
|
||||||
|
text: list[str]
|
||||||
|
fg_color: list[str]
|
||||||
|
bg_color: list[str]
|
||||||
|
palette: list[int]
|
||||||
|
|
||||||
|
|
||||||
|
class Update(BaseModel):
|
||||||
|
screen: ScreenContent | None
|
||||||
|
|
||||||
|
|
||||||
|
class WSManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.computers: dict[UUID, WebSocket] = dict()
|
||||||
|
self.viewers: dict[UUID, set[WebSocket]] = dict()
|
||||||
|
self.queue: asyncio.Queue[tuple[UUID, any]] = asyncio.Queue()
|
||||||
|
|
||||||
|
async def send_connect(self, id: str):
|
||||||
|
if id not in self.computers:
|
||||||
|
return
|
||||||
|
|
||||||
|
await self.computers[id].send_json({"type": "viewer_connect"})
|
||||||
|
|
||||||
|
async def send_disconnect(self, id: str):
|
||||||
|
if id not in self.computers:
|
||||||
|
return
|
||||||
|
|
||||||
|
await self.computers[id].send_json({"type": "viewer_disconnect"})
|
||||||
|
|
||||||
|
async def queue_task(self):
|
||||||
|
print("[WS] queue task started")
|
||||||
|
while True:
|
||||||
|
(uuid, message) = await self.queue.get()
|
||||||
|
|
||||||
|
if uuid not in self.viewers:
|
||||||
|
continue
|
||||||
|
|
||||||
|
viewers = self.viewers[uuid]
|
||||||
|
await asyncio.gather(*(viewer.send_json(message) for viewer in viewers))
|
||||||
|
|
||||||
|
async def broadcast(self, id: str, message):
|
||||||
|
await self.queue.put((id, message))
|
||||||
|
|
||||||
|
async def on_computer_connect(self, socket: WebSocket, id: str):
|
||||||
|
if id in self.computers:
|
||||||
|
print(f"[WS] Closing duplicate connection for {id}")
|
||||||
|
await socket.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
await create_event("computer_connect", computer_id=str(id))
|
||||||
|
self.computers[id] = socket
|
||||||
|
|
||||||
|
if len(self.viewers.get(id, [])) > 0:
|
||||||
|
await self.send_connect(id)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = await socket.receive_json()
|
||||||
|
data = Update.parse_obj(data)
|
||||||
|
|
||||||
|
if data.screen:
|
||||||
|
await self.broadcast(id, data.screen.dict())
|
||||||
|
|
||||||
|
except ValidationError as e:
|
||||||
|
print(f"[WS] Received invalid message from {id}:")
|
||||||
|
print(e.json)
|
||||||
|
except WebSocketDisconnect:
|
||||||
|
break
|
||||||
|
|
||||||
|
del self.computers[id]
|
||||||
|
await create_event("computer_disconnect", computer_id=str(id))
|
||||||
|
|
||||||
|
async def on_browser_connect(self, socket: WebSocket, id: str):
|
||||||
|
print(f"[WS] Browser connected for {id}")
|
||||||
|
|
||||||
|
if id not in self.viewers:
|
||||||
|
self.viewers[id] = set()
|
||||||
|
|
||||||
|
if len(self.viewers[id]) == 0:
|
||||||
|
await self.send_connect(id)
|
||||||
|
|
||||||
|
self.viewers[id].add(socket)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = await socket.receive_json()
|
||||||
|
except WebSocketDisconnect:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.viewers[id].remove(socket)
|
||||||
|
if len(self.viewers[id]) == 0:
|
||||||
|
await self.send_disconnect(id)
|
||||||
|
|
||||||
|
print(f"[WS] Browser disconnected for {id}")
|
||||||
|
|
||||||
|
|
||||||
|
ws_manager = WSManager()
|
||||||
|
|
||||||
|
|
||||||
|
@monitoring.websocket("/computer/{id}/ws")
|
||||||
|
async def computer_ws(
|
||||||
|
socket: WebSocket, id: str, validation=Depends(validate_computer)
|
||||||
|
):
|
||||||
|
await socket.accept()
|
||||||
|
await ws_manager.on_computer_connect(socket, id)
|
||||||
|
|
||||||
|
|
||||||
|
@monitoring.websocket("/browser/{id}/ws")
|
||||||
|
async def browser_ws(socket: WebSocket, id: str):
|
||||||
|
await socket.accept()
|
||||||
|
await ws_manager.on_browser_connect(socket, id)
|
||||||
@@ -6,6 +6,12 @@ class Settings(BaseSettings):
|
|||||||
dev_npm_port: int = 5173
|
dev_npm_port: int = 5173
|
||||||
|
|
||||||
frontend_path: str = "frontend"
|
frontend_path: str = "frontend"
|
||||||
|
unmined_out_path: str = "unmined-out"
|
||||||
|
lua_out_path: str = "lua"
|
||||||
|
|
||||||
|
mongo_uri: str
|
||||||
|
|
||||||
|
deploy_path: str = "http://localhost:8000"
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|||||||
6
server/server/templates.py
Normal file
6
server/server/templates.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||||
|
|
||||||
|
j2env = Environment(
|
||||||
|
loader=FileSystemLoader("templates"),
|
||||||
|
autoescape=select_autoescape(),
|
||||||
|
)
|
||||||
5
server/templates/auth.lua
Normal file
5
server/templates/auth.lua
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
return {
|
||||||
|
id = "{{ id }}",
|
||||||
|
token = "{{ token }}",
|
||||||
|
server = "{{ server }}"
|
||||||
|
}
|
||||||
23
server/templates/install.lua
Normal file
23
server/templates/install.lua
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
local args = { ... }
|
||||||
|
local token = args[1]
|
||||||
|
|
||||||
|
local existing = fs.exists("auth.lua")
|
||||||
|
if not token and not existing then
|
||||||
|
error("A token is required.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local path = "{{ deploy_path }}"
|
||||||
|
if existing then
|
||||||
|
print("Found auth.lua, skipping")
|
||||||
|
elseif token then
|
||||||
|
print("Using token...")
|
||||||
|
shell.run(("wget %s/api/issue-id/%s auth.lua"):format(path, token))
|
||||||
|
if not fs.exists("auth.lua") then
|
||||||
|
error("Token failed!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local files = { {% for filename in file_list %} "{{ filename }}", {% endfor %} }
|
||||||
|
for _, file in ipairs(files) do
|
||||||
|
fs.delete(file)
|
||||||
|
shell.run(("wget %s/lua/%s %s"):format(path, file, file))
|
||||||
|
end
|
||||||
12
server/templates/metadata.js
Normal file
12
server/templates/metadata.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/* {{ props_file }} */
|
||||||
|
{{ map_props }}
|
||||||
|
/* end of {{ props_file }} */
|
||||||
|
|
||||||
|
/* {{ regions_file }} */
|
||||||
|
{{map_regions}}
|
||||||
|
/* end of {{ regions_file }} */
|
||||||
|
|
||||||
|
return {
|
||||||
|
properties: UnminedMapProperties,
|
||||||
|
regions: UnminedRegions,
|
||||||
|
}
|
||||||
5
server/templates/unmined.js
Normal file
5
server/templates/unmined.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/* {{ unmined_file }} */
|
||||||
|
{{ unmined_script }}
|
||||||
|
/* end of {{ unmined_file }} */
|
||||||
|
|
||||||
|
return new Unmined();
|
||||||
Reference in New Issue
Block a user