Compare commits
173 Commits
Author | SHA1 | Date |
---|---|---|
Jef Roosens | d8b0d35c40 | |
Jef Roosens | 6c7df4b30e | |
Jef Roosens | 6ff4cef5d4 | |
Jef Roosens | a1a0f38f74 | |
Renovate Bot | 1d83ee4338 | |
Renovate Bot | 2f66ce4e22 | |
Renovate Bot | 9cbdfff62f | |
Renovate Bot | 7dfb3c0e20 | |
Jef Roosens | fe9c19f0e8 | |
Renovate Bot | f4aba0c16f | |
Jef Roosens | 7cebe510f7 | |
Renovate Bot | d4872e9c48 | |
Jef Roosens | a35b9a73f1 | |
Renovate Bot | af8660f99e | |
Jef Roosens | 8207e104ae | |
Renovate Bot | 4e24ad8988 | |
Jef Roosens | a826d4272a | |
Renovate Bot | f6faaf0db9 | |
Jef Roosens | 204f8f0a56 | |
Jef Roosens | cc9ff7635c | |
Jef Roosens | 6d95ffd372 | |
Jef Roosens | 237568d5e4 | |
Jef Roosens | be797de526 | |
Jef Roosens | 03020fe798 | |
Renovate Bot | 82bb4c6a6e | |
Jef Roosens | 4cf9152fc4 | |
Jef Roosens | 8baeda4cae | |
Jef Roosens | 2547434d95 | |
Jef Roosens | b9d0bb7aa5 | |
Jef Roosens | faa4f713c8 | |
Jef Roosens | c8bfc16af8 | |
Jef Roosens | 9dbb4c8804 | |
Jef Roosens | 728e72e47c | |
Jef Roosens | 01aa4bae80 | |
Jef Roosens | 2a14703097 | |
Jef Roosens | 81c0d5e00b | |
Jef Roosens | 63316314aa | |
Jef Roosens | 0ec5e33860 | |
Jef Roosens | 9d065c229e | |
Jef Roosens | b8f31aa337 | |
Jef Roosens | bd51b6ce14 | |
Jef Roosens | 4666790784 | |
Jef Roosens | 92c6e2c5cc | |
Jef Roosens | ff1631b525 | |
Jef Roosens | cd4075d294 | |
Jef Roosens | 785acd5c2e | |
Renovate Bot | 48802dbc3c | |
Jef Roosens | 487edf9ebd | |
Renovate Bot | d7ee53e62c | |
Jef Roosens | f9da125b4a | |
Jef Roosens | 135e74e6e3 | |
Renovate Bot | 5725b91c61 | |
Jef Roosens | 336ff25249 | |
Jef Roosens | 3bbc90ad60 | |
Jef Roosens | 472f890a98 | |
Jef Roosens | 3f5c0d038b | |
Jef Roosens | fd6b3ed134 | |
Jef Roosens | 92a08a17af | |
Jef Roosens | 9946aaf001 | |
Jef Roosens | 1da94c5211 | |
Jef Roosens | 6532fbebb1 | |
Jef Roosens | 0b86ed9254 | |
Jef Roosens | d2e6028104 | |
Renovate Bot | 9f31c69777 | |
Renovate Bot | 39ad811429 | |
Jef Roosens | bef7505631 | |
Jef Roosens | 5ce3f0bb39 | |
Jef Roosens | e67616baa1 | |
Jef Roosens | 36bd27c919 | |
Renovate Bot | 1cf009c212 | |
Jef Roosens | e179b1eadb | |
Renovate Bot | e5b872acdf | |
Jef Roosens | a738951961 | |
Renovate Bot | 8e3425749f | |
Jef Roosens | f27775910f | |
Jef Roosens | 4b3ae8a9a4 | |
Jef Roosens | d2ad0591f6 | |
Jef Roosens | 28bb959c12 | |
Jef Roosens | 5a95ee5270 | |
Jef Roosens | e0ac8ddd24 | |
Jef Roosens | 628a918682 | |
Jef Roosens | 0055667877 | |
Jef Roosens | 687632a704 | |
Jef Roosens | 659632eba5 | |
Jef Roosens | 77e04d5b6b | |
Jef Roosens | 2c75e29e1b | |
Jef Roosens | 683e48281f | |
Renovate Bot | caa92377f6 | |
Jef Roosens | 3bdf79e824 | |
Jef Roosens | 0abfaca967 | |
Jef Roosens | 62738354a0 | |
Jef Roosens | 2a4153d430 | |
Jef Roosens | 9e428b1882 | |
Renovate Bot | 0082076527 | |
Jef Roosens | 7ccfe6eebf | |
Jef Roosens | f1416aaa48 | |
Renovate Bot | 26ec8b4eba | |
Renovate Bot | b93d771372 | |
Jef Roosens | e5b9c285fa | |
Renovate Bot | bf8a0ae666 | |
Jef Roosens | ecec03134a | |
Jef Roosens | 5b0e595253 | |
Jef Roosens | 85611e2d59 | |
Jef Roosens | 0877cc590c | |
Jef Roosens | 91985a1710 | |
Jef Roosens | 95564e8111 | |
Jef Roosens | a0e55e4830 | |
Jef Roosens | 2c8f1ac601 | |
Jef Roosens | fee37420cd | |
Jef Roosens | e62cd0bb93 | |
Jef Roosens | 6beca85154 | |
Jef Roosens | a072941ec3 | |
Jef Roosens | 95f45cab76 | |
Jef Roosens | 43e26191cc | |
Jef Roosens | 00bf8501dd | |
Jef Roosens | 65c3d616de | |
Jef Roosens | d43a34a5d6 | |
Jef Roosens | 0bd09db295 | |
Jef Roosens | adbe6d1fb7 | |
Jef Roosens | 0b2b986205 | |
Jef Roosens | 758a332138 | |
Jef Roosens | 3a490fca35 | |
Jef Roosens | 5746d29556 | |
Jef Roosens | f381c5b910 | |
Jef Roosens | fd7a3e2331 | |
Jef Roosens | d5a513482a | |
Jef Roosens | 14321db316 | |
Jef Roosens | 915ab9ea25 | |
Jef Roosens | 5534df00dc | |
Jef Roosens | 0e4eb68121 | |
Jef Roosens | c2fa764e80 | |
Jef Roosens | 45c4a4e257 | |
Jef Roosens | 4b51ee20ca | |
Jef Roosens | d19fe5c42e | |
Jef Roosens | bffbb61124 | |
Jef Roosens | 0828dd36d6 | |
Jef Roosens | 0ba31bd8ba | |
Jef Roosens | 22e9dcceaf | |
Jef Roosens | 21e142e9a4 | |
Jef Roosens | cb78af62ba | |
Jef Roosens | 37c9b397b4 | |
Jef Roosens | 81ae1a2555 | |
Jef Roosens | 727589b10f | |
Jef Roosens | 5e28949b5c | |
Jef Roosens | 6954921df6 | |
Jef Roosens | 5b515ecd91 | |
Jef Roosens | 969306bbae | |
Jef Roosens | c9b7714a47 | |
Jef Roosens | 466efa95ef | |
Jef Roosens | 87f2659b48 | |
Jef Roosens | 9ee542197d | |
Jef Roosens | 452683f4d7 | |
Jef Roosens | 5f98b65902 | |
Jef Roosens | d466ab6d13 | |
Jef Roosens | bdd27446eb | |
Jef Roosens | fe6a5f81b3 | |
Jef Roosens | 75ffdfdc27 | |
Jef Roosens | cfa0a8cf22 | |
Jef Roosens | 00926162fa | |
Jef Roosens | baca622340 | |
Jef Roosens | 760e9fa584 | |
Jef Roosens | 98faade91f | |
Jef Roosens | 4a32349c9c | |
Jef Roosens | 3b5f1e9cf7 | |
Jef Roosens | 552cf4bf7b | |
Jef Roosens | dddde5074a | |
Jef Roosens | 6d4cf6feb6 | |
Jef Roosens | c51401f7d8 | |
Jef Roosens | 34b32a3252 | |
Jef Roosens | 93ec27bb02 | |
Jef Roosens | c6518a33b1 | |
Jef Roosens | c8a06f7af9 | |
Jef Roosens | 8bff21b346 |
|
@ -1,8 +1,42 @@
|
|||
*
|
||||
|
||||
# Source code
|
||||
# =====BACKEND=====
|
||||
## Source code
|
||||
!src/
|
||||
|
||||
# Cargo files
|
||||
## Cargo files
|
||||
!Cargo.toml
|
||||
!Cargo.lock
|
||||
|
||||
## Entrypoint for devop container
|
||||
!docker/entrypoint_dev.sh
|
||||
!docker/entrypoint.sh
|
||||
|
||||
## Config file
|
||||
!Rocket.toml
|
||||
|
||||
## Database migrations
|
||||
!migrations/
|
||||
|
||||
## Crontab for release container
|
||||
!docker/crontab
|
||||
|
||||
|
||||
# =====FRONTEND=====
|
||||
## Source code
|
||||
!web/src/
|
||||
|
||||
## Public assets
|
||||
!web/public/
|
||||
!web/index.html
|
||||
|
||||
## Production env file
|
||||
!web/.env.production
|
||||
|
||||
## Package manager stuff
|
||||
!web/package.json
|
||||
!web/yarn.lock
|
||||
|
||||
## Project configs
|
||||
!web/tsconfig.json
|
||||
!web/vite.config.ts
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = false
|
||||
indent_style = space
|
||||
indent_size = 4
|
|
@ -0,0 +1,2 @@
|
|||
# This file is read by diesel
|
||||
DATABASE_URL=postgres://fej:fej@localhost:5432/fej
|
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This hook lints the code, and if we're on develop or master, also forces the tests to pass.
|
||||
make lint &> /dev/null 2>&1 || {
|
||||
>&2 echo "Format check failed, use 'make lint' for more information.";
|
||||
./fejctl lint &> /dev/null 2>&1 || {
|
||||
>&2 echo "Format check failed, use './fejctl lint' for more information.";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
branch=`git rev-parse --abbrev-ref HEAD`
|
||||
# branch=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
# TODO should we add release branches here as well?
|
||||
if [[ "$branch" =~ ^master|develop$ ]]; then
|
||||
make test > /dev/null 2>&1 || {
|
||||
>&2 echo "Tests failed. check 'make test' for more info.";
|
||||
exit 1;
|
||||
}
|
||||
fi
|
||||
# # TODO should we add release branches here as well?
|
||||
# if [[ "$branch" =~ ^master|develop$ ]]; then
|
||||
# make test > /dev/null 2>&1 || {
|
||||
# >&2 echo "Tests failed. check 'make test' for more info.";
|
||||
# exit 1;
|
||||
# }
|
||||
# fi
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
pipeline:
|
||||
# Download the cache from S3
|
||||
restore-cache:
|
||||
image: plugins/s3-cache
|
||||
pull: true
|
||||
|
||||
endpoint: https://s3.roosens.me
|
||||
root: build-cache/
|
||||
restore: true
|
||||
|
||||
secrets: [ cache_s3_access_key, cache_s3_secret_key ]
|
||||
|
||||
|
||||
# =====BUILDING=====
|
||||
build-frontend:
|
||||
image: node:15-alpine3.13
|
||||
pull: true
|
||||
group: build
|
||||
commands:
|
||||
- cd web
|
||||
- yarn install
|
||||
- yarn run build
|
||||
|
||||
build-backend:
|
||||
image: chewingbever/fej-builder:latest
|
||||
pull: true
|
||||
group: build
|
||||
environment:
|
||||
- CARGO_HOME=.cargo
|
||||
commands:
|
||||
- cargo build
|
||||
|
||||
|
||||
# =====TESTING=====
|
||||
test-backend:
|
||||
image: chewingbever/fej-builder:latest
|
||||
environment:
|
||||
- CARGO_HOME=.cargo
|
||||
commands:
|
||||
- cargo test
|
||||
|
||||
|
||||
# =====LINTING=====
|
||||
lint-frontend:
|
||||
image: node:15-alpine3.13
|
||||
group: lint
|
||||
commands:
|
||||
- cd web
|
||||
- yarn run lint
|
||||
|
||||
lint-backend:
|
||||
image: chewingbever/fej-builder:latest
|
||||
group: lint
|
||||
environment:
|
||||
- CARGO_HOME=.cargo
|
||||
commands:
|
||||
- cargo fmt -- --check
|
||||
# This is run here because it requires compilation
|
||||
- cargo clippy --all-targets -- -D warnings
|
||||
|
||||
|
||||
# =====REBUILD & FLUSH CACHE=====
|
||||
rebuild-cache:
|
||||
image: plugins/s3-cache
|
||||
|
||||
endpoint: https://s3.roosens.me
|
||||
root: build-cache/
|
||||
rebuild: true
|
||||
mount:
|
||||
- target
|
||||
- .cargo
|
||||
- web/node_modules
|
||||
|
||||
secrets: [ cache_s3_access_key, cache_s3_secret_key ]
|
||||
# Push the cache, even on failure
|
||||
when:
|
||||
status: [ success, failure ]
|
||||
|
||||
flush-cache:
|
||||
image: plugins/s3-cache
|
||||
|
||||
endpoint: https://s3.roosens.me
|
||||
root: build-cache/
|
||||
flush: true
|
||||
# Delete cache older than 30 days (might lower this)
|
||||
flush_age: 14
|
||||
|
||||
secrets: [ cache_s3_access_key, cache_s3_secret_key ]
|
||||
# Push the cache, even on failure
|
||||
when:
|
||||
status: [ success, failure ]
|
|
@ -58,9 +58,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -98,12 +98,6 @@ dependencies = [
|
|||
"safemem",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
|
@ -195,9 +189,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.5"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
|
||||
checksum = "402da840495de3f976eaefc3485b7f5eb5b0bf9761f9a47be27fe975b3b8c2ec"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
|
@ -233,7 +227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3818dfca4b0cb5211a659bbcbb94225b7127407b2b135e650d717bfb78ab10d3"
|
||||
dependencies = [
|
||||
"cookie 0.14.4",
|
||||
"idna 0.2.2",
|
||||
"idna 0.2.3",
|
||||
"log 0.4.14",
|
||||
"publicsuffix",
|
||||
"serde",
|
||||
|
@ -321,6 +315,40 @@ dependencies = [
|
|||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel"
|
||||
version = "1.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"diesel_derives",
|
||||
"pq-sys",
|
||||
"r2d2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_derives"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_migrations"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c"
|
||||
dependencies = [
|
||||
"migrations_internals",
|
||||
"migrations_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
|
@ -347,10 +375,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fej"
|
||||
version = "0.1.0"
|
||||
version = "1.0.2"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"diesel",
|
||||
"diesel_migrations",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
|
@ -438,42 +468,42 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
|||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
||||
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
||||
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
|
@ -523,9 +553,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
|||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d832b01df74254fe364568d6ddc294443f61cbec82816b60904303af87efae78"
|
||||
checksum = "fc018e188373e2777d0ef2467ebff62a08e66c3f5857b23c8fbec3018210dc00"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -577,9 +607,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747"
|
||||
checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -599,9 +629,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.3.5"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
|
||||
checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
|
@ -630,9 +660,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.4"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7"
|
||||
checksum = "8bf09f61b52cfcf4c00de50df88ae423d6c02354e385a86341133b5338630ad1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
@ -659,7 +689,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper 0.14.4",
|
||||
"hyper 0.14.5",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
|
@ -678,9 +708,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
|
||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"unicode-bidi",
|
||||
|
@ -717,6 +747,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
|
@ -740,9 +779,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.49"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821"
|
||||
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -777,9 +816,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.91"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -807,9 +855,30 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
|
||||
|
||||
[[package]]
|
||||
name = "migrations_internals"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "migrations_macros"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
||||
dependencies = [
|
||||
"migrations_internals",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
|
@ -922,9 +991,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "4.0.15"
|
||||
version = "4.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd"
|
||||
checksum = "2599080e87c9bd051ddb11b10074f4da7b1223298df65d4c2ec5bcf309af1533"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"filetime",
|
||||
|
@ -1021,6 +1090,31 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
|
@ -1066,22 +1160,22 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.5"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63"
|
||||
checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.5"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
|
||||
checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1119,6 +1213,15 @@ version = "0.2.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "pq-sys"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda"
|
||||
dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
|
@ -1136,9 +1239,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
@ -1149,7 +1252,7 @@ version = "1.5.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f"
|
||||
dependencies = [
|
||||
"idna 0.2.2",
|
||||
"idna 0.2.3",
|
||||
"url 2.2.1",
|
||||
]
|
||||
|
||||
|
@ -1168,7 +1271,18 @@ version = "1.0.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r2d2"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f"
|
||||
dependencies = [
|
||||
"log 0.4.14",
|
||||
"parking_lot",
|
||||
"scheduled-thread-pool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1213,18 +1327,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.5"
|
||||
version = "1.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -1233,9 +1347,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.23"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
|
@ -1248,9 +1362,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4"
|
||||
checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes",
|
||||
|
@ -1261,7 +1375,7 @@ dependencies = [
|
|||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper 0.14.4",
|
||||
"hyper 0.14.5",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
|
@ -1286,12 +1400,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rocket"
|
||||
version = "0.4.7"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7febfdfd4d43facfc7daba20349ebe2c310c6735bd6a2a9255ea8bc425b4cb13"
|
||||
checksum = "4a7ab1dfdc75bb8bd2be381f37796b1b300c45a3c9145b34d86715e8dd90bf28"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"base64 0.12.3",
|
||||
"base64 0.13.0",
|
||||
"log 0.4.14",
|
||||
"memchr",
|
||||
"num_cpus",
|
||||
|
@ -1307,9 +1421,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rocket_codegen"
|
||||
version = "0.4.7"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ceac2c55b2c8b1cdc53add64332defa5fc227f64263b86b4114d1386286d42a3"
|
||||
checksum = "1729e687d6d2cf434d174da84fb948f7fef4fac22d20ce94ca61c28b72dbcf9f"
|
||||
dependencies = [
|
||||
"devise",
|
||||
"glob",
|
||||
|
@ -1322,22 +1436,37 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rocket_contrib"
|
||||
version = "0.4.7"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7954a707f9ca18aa74ca8c1f5d1f900f52a4dceb68e96e3112143f759cfd20e"
|
||||
checksum = "6b6303dccab46dce6c7ac26c9b9d8d8cde1b19614b027c3f913be6611bff6d9b"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
"log 0.4.14",
|
||||
"notify",
|
||||
"r2d2",
|
||||
"rocket",
|
||||
"rocket_contrib_codegen",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket_http"
|
||||
version = "0.4.7"
|
||||
name = "rocket_contrib_codegen"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce364100ed7a1bf39257b69ebd014c1d5b4979b0d365d8c9ab0aa9c79645493d"
|
||||
checksum = "a0f2cbcb6c09b3ac0acdf77682ff8c9d1f317361498a773ee50b32be7fddfe2b"
|
||||
dependencies = [
|
||||
"devise",
|
||||
"quote 0.6.13",
|
||||
"version_check 0.9.3",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket_http"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6131e6e6d38a9817f4a494ff5da95971451c2eb56a53915579fc9c80f6ef0117"
|
||||
dependencies = [
|
||||
"cookie 0.11.4",
|
||||
"hyper 0.10.16",
|
||||
|
@ -1391,10 +1520,25 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.1.2"
|
||||
name = "scheduled-thread-pool"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d493c5f39e02dfb062cd8f33301f90f9b13b650e8c1b1d0fd75c19dd64bff69d"
|
||||
checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7"
|
||||
dependencies = [
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
|
@ -1405,9 +1549,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d"
|
||||
checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -1430,22 +1574,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.125"
|
||||
version = "1.0.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.125"
|
||||
version = "1.0.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1504,11 +1648,10 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
|||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.19"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||
checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
@ -1548,11 +1691,11 @@ version = "0.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1562,13 +1705,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
||||
dependencies = [
|
||||
"base-x",
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1596,11 +1739,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.64"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
|
||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
@ -1662,17 +1805,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"standback",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
|
||||
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
@ -1685,9 +1828,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722"
|
||||
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
|
@ -1710,9 +1853,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.5"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f"
|
||||
checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
@ -1792,9 +1935,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.4"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
|
||||
dependencies = [
|
||||
"matches",
|
||||
]
|
||||
|
@ -1848,16 +1991,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna 0.2.2",
|
||||
"idna 0.2.3",
|
||||
"matches",
|
||||
"percent-encoding 2.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.11"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
|
||||
checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
|
@ -1900,9 +2043,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.72"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe"
|
||||
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
|
@ -1912,24 +2055,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.72"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3"
|
||||
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log 0.4.14",
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.22"
|
||||
version = "0.4.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73157efb9af26fb564bb59a009afd1c7c334a44db171d280690d0c3faaec3468"
|
||||
checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
|
@ -1939,9 +2082,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.72"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b"
|
||||
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
|
||||
dependencies = [
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -1949,28 +2092,28 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.72"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d"
|
||||
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"syn 1.0.69",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.72"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa"
|
||||
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.49"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310"
|
||||
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
|
41
Cargo.toml
41
Cargo.toml
|
@ -1,37 +1,48 @@
|
|||
[package]
|
||||
name = "fej"
|
||||
version = "0.1.0"
|
||||
version = "1.0.2"
|
||||
authors = ["Jef Roosens <roosensjef@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
# Enables hosting of the frontend
|
||||
frontend = []
|
||||
|
||||
[lib]
|
||||
name = "fej_lib"
|
||||
src = "src/lib.rs"
|
||||
name = "fej"
|
||||
path = "src/fej/lib.rs"
|
||||
test = true
|
||||
bench = true
|
||||
doc = true
|
||||
doctest = true
|
||||
|
||||
[[bin]]
|
||||
name = "fej"
|
||||
src = "src/main.rs"
|
||||
name = "server"
|
||||
path = "src/server/main.rs"
|
||||
test = true
|
||||
bench = true
|
||||
doc = true
|
||||
doctest = true
|
||||
|
||||
[[bin]]
|
||||
name = "populate_ivago"
|
||||
path = "src/populate_ivago.rs"
|
||||
test = false
|
||||
bench = false
|
||||
doc = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
rocket = "0.4.7"
|
||||
serde = "1.0.124"
|
||||
rocket = "0.4.10"
|
||||
serde = "1.0.126"
|
||||
chrono = "0.4.19"
|
||||
chrono-tz = "0.5.3"
|
||||
regex = "1.4.5"
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.11.2"
|
||||
default-features = true
|
||||
features = ["blocking", "json", "cookies"]
|
||||
regex = "1.5.4"
|
||||
reqwest = { version = "0.11.3", features = ["blocking", "json", "cookies"] }
|
||||
diesel = { version = "1.4.8", features = ["postgres"] }
|
||||
diesel_migrations = "1.4.0"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
version = "0.4.7"
|
||||
version = "0.4.10"
|
||||
default-features = false
|
||||
features = ["json"]
|
||||
features = ["json", "diesel_postgres_pool", "serve"]
|
||||
|
|
37
Dockerfile
37
Dockerfile
|
@ -1,37 +0,0 @@
|
|||
# syntax = docker/dockerfile:1.2
|
||||
|
||||
# We use a multi-stage build to end up with a very small final image
|
||||
FROM alpine:latest AS builder
|
||||
|
||||
ENV PATH "$PATH:/root/.cargo/bin"
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install build dependencies, rustup & rust's nightly build & toolchain
|
||||
RUN apk update && apk add --no-cache openssl-dev build-base curl && \
|
||||
{ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; }
|
||||
|
||||
# Copy source code over to builder
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
COPY src/ ./src/
|
||||
|
||||
# Run the tests, don't want no broken docker image
|
||||
# And then finally, build the project
|
||||
# Thank the lords that this article exists
|
||||
# https://users.rust-lang.org/t/sigsegv-with-program-linked-against-openssl-in-an-alpine-container/52172
|
||||
# TODO add what these flags do & why they work
|
||||
# NOTE: cargo install auto-appends bin to the path
|
||||
RUN --mount=type=cache,target=/usr/src/app/target RUSTFLAGS="-C target-feature=-crt-static" cargo test && \
|
||||
RUSTFLAGS="-C target-feature=-crt-static" cargo install --path . --bin fej --root /usr/local
|
||||
|
||||
|
||||
# Now, we create the actual image
|
||||
FROM alpine:latest
|
||||
|
||||
# Install some dynamic libraries needed for everything to work
|
||||
RUN apk update && apk add --no-cache openssl libgcc
|
||||
|
||||
# Copy binary over to final image
|
||||
COPY --from=builder /usr/local/bin/fej /usr/local/bin/fej
|
||||
|
||||
CMD ["/usr/local/bin/fej"]
|
143
LICENSE
143
LICENSE
|
@ -1,5 +1,5 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
|
@ -7,17 +7,15 @@
|
|||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
|
@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
|||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
@ -72,7 +60,7 @@ modification follow.
|
|||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
|||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
|
@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
|
47
Makefile
47
Makefile
|
@ -1,47 +0,0 @@
|
|||
IMAGE := chewingbever/fej
|
||||
|
||||
|
||||
all: debug
|
||||
.PHONY: all
|
||||
|
||||
# Builds
|
||||
debug:
|
||||
@ cargo build
|
||||
.PHONY: debug
|
||||
|
||||
release:
|
||||
@ cargo build --release
|
||||
.PHONY: release
|
||||
|
||||
image: Dockerfile
|
||||
@ ./build '$(IMAGE)'
|
||||
.PHONY: image
|
||||
|
||||
push:
|
||||
@ ./build '$(IMAGE)' push
|
||||
.PHONY: push
|
||||
|
||||
# Run
|
||||
run:
|
||||
@ RUST_BACKTRACE=1 cargo run --bin fej
|
||||
.PHONY: run
|
||||
|
||||
|
||||
# Testing
|
||||
test:
|
||||
@ cargo test --no-fail-fast
|
||||
.PHONY: test
|
||||
|
||||
format:
|
||||
@ cargo fmt
|
||||
.PHONY: format
|
||||
|
||||
lint:
|
||||
@ cargo fmt -- --check
|
||||
.PHONY: lint
|
||||
|
||||
|
||||
# Documentation
|
||||
docs:
|
||||
@ cargo doc --no-deps
|
||||
.PHONY: docs
|
58
README.md
58
README.md
|
@ -1,22 +1,52 @@
|
|||
# Fej
|
||||
|
||||
Fej is an API written in Rust. I started this project to learn the language,
|
||||
and really just have some fun.
|
||||
Fej is a RESTful API that does lots of different things. It started as an
|
||||
experiment to learn Rust, but has grown into a full-on passion project.
|
||||
|
||||
## Project Structure
|
||||
|
||||
The folder structure follows the structure of the URLs, e.g. the route for
|
||||
`/hello/world` is found in the module `src/hello`.
|
||||
The `src` folder contains subfolders for the various binaries and the main
|
||||
library, called `fej`. The biggest binary is called `server`, which is the
|
||||
binary that actually runs the Rocket.rs web server. All the others are utility
|
||||
programs, mostly consisting of scrapers for various services.
|
||||
|
||||
Each module contains the following base files:
|
||||
Version 1.1 also introduces the use of a database, namely
|
||||
[PostgreSQL 13](https://www.postgresql.org/).
|
||||
|
||||
* `mod.rs`: defines the modules' content, and contains the route definitions.
|
||||
The route functions themselves only contain the functionality needed to
|
||||
represent the data, not acquire it.
|
||||
* `controller.rs`: this file contains the actual logic of each route. If the
|
||||
logic becomes too complicated to be contained inside a single file,
|
||||
`controller.rs` becomes its own module folder named `controller`.
|
||||
* `tests.rs`: this contains tests for the specific module. This can also be a
|
||||
module directory if need be.
|
||||
## Roadmap
|
||||
|
||||
Every module has a `routes` function that returns its route macros.
|
||||
See [roadmap.md](roadmap.md).
|
||||
|
||||
## Development
|
||||
|
||||
To make development more consistent (and keep my computer a bit cleaner) I've
|
||||
decided to run the entire toolchain using Docker, with Alpine Linux base
|
||||
images. This also allows me to make really small final images. Technically,
|
||||
Docker is the only dependency you need to contribute to this project
|
||||
(not accounting for language servers etc.).
|
||||
|
||||
A [Bash script](fejctl) is provided to speed up development on the various
|
||||
binaries. It aids in starting up the containers, choosing which binary to run
|
||||
etc. A quick rundown of its most important features:
|
||||
|
||||
```bash
|
||||
# By default, it compiles the 'server' binary (but doesn't run it)
|
||||
./fejctl
|
||||
|
||||
# The first argument is the action you wish to perform, the second on which
|
||||
# binary (not all commands need a binary as input, so they just ignore it)
|
||||
# For example, this will run the binary called server
|
||||
./fejctl r server
|
||||
|
||||
# This runs the tests (all commands also have their full name if you want)
|
||||
./fejctl t
|
||||
./fejctl test
|
||||
|
||||
# These attach to the two containers
|
||||
./fejctl sh # Opens a new root shell inside the 'fej' container
|
||||
./fejctl psql # Open a new psql shell in the fej database
|
||||
```
|
||||
|
||||
## Docker images
|
||||
|
||||
The images are available [here](https://hub.docker.com/r/chewingbever/fej).
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
[development]
|
||||
address = "0.0.0.0"
|
||||
port = 8000
|
||||
keep_alive = 5
|
||||
read_timeout = 5
|
||||
write_timeout = 5
|
||||
log = "normal"
|
||||
limits = { forms = 32768 }
|
||||
|
||||
[development.databases]
|
||||
postgres_fej = { url = "postgres://fej:fej@fej_db:5432/fej" }
|
||||
|
||||
[production.databases]
|
||||
postgres_fej = { url = "postgres://fej:fej@db:5432/fej" }
|
55
build
55
build
|
@ -1,55 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Simple guard to check input args
|
||||
[[ $# -eq 1 ]] || [[ $# -eq 2 ]] || {
|
||||
>&2 echo "Usage: ./build IMAGE [ACTION]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extract current version from Cargo.toml & get current branch
|
||||
patch_version="$(grep -Po '(?<=version = ").*(?=")' Cargo.toml | head -n1)"
|
||||
major_version="$(echo "$patch_version" |
|
||||
sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1/')"
|
||||
minor_version="$(echo "$patch_version" |
|
||||
sed -E 's/([0-9]+).([0-9]+).([0-9]+)/\1.\2/')"
|
||||
branch="$(git branch --show-current)"
|
||||
|
||||
if [[ "$branch" = "master" ]]; then
|
||||
tags=("$patch_version" "$minor_version" "$major_version" "latest")
|
||||
|
||||
elif [[ "$branch" = "develop" ]]; then
|
||||
tags=("$patch_version-dev" "$minor_version-dev" "$major_version-dev" "dev")
|
||||
|
||||
else
|
||||
tags=("$branch")
|
||||
|
||||
fi
|
||||
|
||||
# Run the actual build command
|
||||
DOCKER_BUILDKIT=1 docker build -t "$1:$tags" .
|
||||
|
||||
if [[ "$2" = push ]]; then
|
||||
[[ "$branch" =~ ^develop|master$ ]] || {
|
||||
>&2 echo "You can only push from develop or master."
|
||||
exit 2
|
||||
}
|
||||
|
||||
for tag in "${tags[@]}"; do
|
||||
# Create the tag
|
||||
docker tag "$1:$tags" "$1:$tag"
|
||||
|
||||
# Push the tag
|
||||
docker push "$1:$tag"
|
||||
|
||||
# Remove the tag again, if it's not the main tag
|
||||
[[ "$tag" != "$tags" ]] && docker rmi "$1:$tag"
|
||||
done
|
||||
|
||||
elif [[ "$2" = run ]]; then
|
||||
docker run \
|
||||
--rm \
|
||||
--interactive \
|
||||
--tty \
|
||||
--publish 8000:8000 \
|
||||
"$1:$tags"
|
||||
fi
|
|
@ -0,0 +1,5 @@
|
|||
# For documentation on how to configure this file,
|
||||
# see diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/fej/schema.rs"
|
|
@ -0,0 +1,25 @@
|
|||
# vim: filetype=dockerfile
|
||||
# Our entire toolchain runs in alpine
|
||||
FROM alpine:3.13.5 AS builder
|
||||
|
||||
ENV PATH "$PATH:/root/.cargo/bin"
|
||||
# Needed for proper compiling of openssl-dev
|
||||
ENV RUSTFLAGS "-C target-feature=-crt-static"
|
||||
|
||||
# Add the build user
|
||||
# Install dependencies
|
||||
RUN addgroup -S builder && \
|
||||
adduser -S builder -G builder -h /app && \
|
||||
apk update && \
|
||||
apk add --no-cache \
|
||||
curl \
|
||||
gcc \
|
||||
libgcc \
|
||||
musl-dev \
|
||||
openssl-dev \
|
||||
postgresql-dev
|
||||
|
||||
# Install rustup in the new user's home
|
||||
# Create mountpoints for volumes with correct permissions
|
||||
RUN { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; } && \
|
||||
rustup target add x86_64-unknown-linux-musl --toolchain nightly
|
|
@ -0,0 +1,13 @@
|
|||
# vim: filetype=dockerfile
|
||||
FROM chewingbever/fej-builder:latest
|
||||
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
# Copy source code over to builder
|
||||
COPY --chown=builder:builder Cargo.toml Cargo.lock ./
|
||||
COPY --chown=builder:builder src/ ./src/
|
||||
COPY --chown=builder:builder migrations/ ./migrations/
|
||||
COPY --chown=builder:builder ./docker/entrypoint_dev.sh /entrypoint.sh
|
||||
COPY --chown=builder:builder ./Rocket.toml /app/Rocket.toml
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
|
@ -0,0 +1,71 @@
|
|||
# vim: filetype=dockerfile
|
||||
FROM chewingbever/fej-builder:latest AS backend-builder
|
||||
|
||||
COPY --chown=builder:builder Cargo.toml Cargo.lock ./
|
||||
COPY --chown=builder:builder src/ ./src/
|
||||
COPY --chown=builder:builder migrations/ ./migrations/
|
||||
|
||||
# And then finally, build the project
|
||||
# Thank the lords that this article exists
|
||||
# https://users.rust-lang.org/t/sigsegv-with-program-linked-against-openssl-in-an-alpine-container/52172
|
||||
# TODO add what these flags do & why they work
|
||||
# NOTE: cargo install auto-appends bin to the path
|
||||
|
||||
# RUN --mount=type=cache,mode=0777,target=/app/target \
|
||||
# --mount=type=cache,mode=0777,target=/app/.cargo/registry \
|
||||
|
||||
# Buildkit cache mounts really don't like it when you're not root,
|
||||
# so I guess we're building release without a cache for now
|
||||
RUN cargo install \
|
||||
--path . \
|
||||
--root /app/output \
|
||||
--target x86_64-unknown-linux-musl \
|
||||
--features frontend
|
||||
|
||||
|
||||
FROM node:17-alpine3.13 AS frontend-builder
|
||||
|
||||
COPY ./web /app
|
||||
WORKDIR /app
|
||||
|
||||
# Build the frontend
|
||||
RUN yarn install && \
|
||||
yarn run build
|
||||
|
||||
|
||||
# Now, we create the actual image
|
||||
FROM alpine:3.13.5
|
||||
COPY ./docker/crontab /var/spool/cron/crontabs/fej
|
||||
|
||||
# Install some dynamic libraries needed for everything to work
|
||||
# Create -non-root user
|
||||
# Change permissions for crontab file
|
||||
RUN apk update && \
|
||||
apk add --no-cache \
|
||||
curl \
|
||||
libgcc \
|
||||
libpq \
|
||||
openssl && \
|
||||
addgroup -S fej && \
|
||||
adduser -S fej -G fej -h /app
|
||||
|
||||
# Switch to non-root user
|
||||
USER fej:fej
|
||||
|
||||
# Copy binary & frontend over to final image
|
||||
COPY --from=backend-builder --chown=fej:fej /app/output/bin /app/bin
|
||||
COPY --from=frontend-builder --chown=fej:fej /app/dist /app/dist
|
||||
|
||||
# Embed config file inside container
|
||||
# The workdir is changed so that the config file is read properly
|
||||
WORKDIR /app
|
||||
COPY --chown=fej:fej Rocket.toml /app/Rocket.toml
|
||||
|
||||
HEALTHCHECK \
|
||||
--interval=10s \
|
||||
--timeout=5s \
|
||||
--start-period=1s \
|
||||
--retries=3 \
|
||||
CMD curl -q localhost:8000
|
||||
|
||||
ENTRYPOINT ["/app/bin/server"]
|
|
@ -0,0 +1,2 @@
|
|||
# Runs the ivago scraper
|
||||
*/30 * * * * /app/bin/populate_ivago
|
|
@ -0,0 +1,31 @@
|
|||
version: '2.4'
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
# Make sure the build context is one directory up
|
||||
context: '..'
|
||||
dockerfile: './docker/Dockerfile.dev'
|
||||
image: 'chewingbever/fej:dev'
|
||||
restart: 'no'
|
||||
|
||||
container_name: 'fej_app'
|
||||
volumes:
|
||||
- 'build-cache:/app/target'
|
||||
- 'registry-cache:/app/.cargo/registry'
|
||||
ports:
|
||||
- '8000:8000'
|
||||
|
||||
command: "${CMD}"
|
||||
|
||||
db:
|
||||
container_name: 'fej_db'
|
||||
restart: 'no'
|
||||
|
||||
# the devop environment exposes the database so we can use the Diesel cli
|
||||
ports:
|
||||
- '5432:5432'
|
||||
|
||||
volumes:
|
||||
build-cache:
|
||||
registry-cache:
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
version: '2.4'
|
||||
|
||||
services:
|
||||
cron:
|
||||
image: 'chewingbever/fej:latest'
|
||||
restart: 'always'
|
||||
|
||||
entrypoint: 'crond -f'
|
||||
user: 'root'
|
||||
healthcheck:
|
||||
disable: true
|
||||
|
||||
environment:
|
||||
- 'DATABASE_URL=postgres://fej:fej@db:5432/fej'
|
|
@ -0,0 +1,34 @@
|
|||
version: '2.4'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: '..'
|
||||
dockerfile: 'docker/Dockerfile.rel'
|
||||
|
||||
image: 'chewingbever/fej:latest'
|
||||
restart: 'always'
|
||||
|
||||
environment:
|
||||
- 'DATABASE_URL=postgres://fej:fej@db:5432/fej'
|
||||
|
||||
db:
|
||||
image: 'postgres:14-alpine'
|
||||
restart: 'always'
|
||||
|
||||
environment:
|
||||
- 'POSTGRES_DB=fej'
|
||||
- 'POSTGRES_USER=fej'
|
||||
- 'POSTGRES_PASSWORD=fej'
|
||||
healthcheck:
|
||||
test: 'pg_isready -U fej'
|
||||
interval: '30s'
|
||||
timeout: '5s'
|
||||
retries: 3
|
||||
start_period: '0s'
|
||||
|
||||
volumes:
|
||||
- 'db-data:/var/lib/postgresql/data'
|
||||
|
||||
volumes:
|
||||
db-data:
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# All this file does is inject the target
|
||||
cargo "$@" --target x86_64-unknown-linux-musl
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
image='chewingbever/fej'
|
||||
web_dir='web'
|
||||
|
||||
# Small wrapper around the docker-compose command
|
||||
#
|
||||
# Flags:
|
||||
# -b: build the builder
|
||||
# -r: use the release image instead
|
||||
function dc() {
|
||||
local OPTIND c build_builder release
|
||||
|
||||
while getopts ":br" c; do
|
||||
case $c in
|
||||
b ) build_builder=1 ;;
|
||||
r ) release=1 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [[ "$release" -eq 1 ]]; then
|
||||
DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1 docker-compose \
|
||||
--file docker/docker-compose.yml \
|
||||
--file docker/docker-compose.override.yml \
|
||||
--project-name fej \
|
||||
"$@"
|
||||
|
||||
else
|
||||
DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1 docker-compose \
|
||||
--file docker/docker-compose.yml \
|
||||
--file docker/docker-compose.dev.yml \
|
||||
--project-name fej-dev \
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute the debug image (must be built first)
|
||||
#
|
||||
# $@: the arguments to pass to the image (passed as arguments to cargo)
|
||||
function dcr() {
|
||||
CMD="$@" dc -b -- up \
|
||||
--build \
|
||||
--detach
|
||||
}
|
||||
|
||||
# Publish the builder image
|
||||
function publish_builder() {
|
||||
DOCKER_BUILDKIT=1 docker build \
|
||||
-f docker/Dockerfile.builder \
|
||||
-t "$image-builder:latest" . || {
|
||||
>&2 echo "Failed to build builder.";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
docker push "$image-builder:latest"
|
||||
}
|
||||
|
||||
# Tags & pushes the release version to Docker Hub
|
||||
function publish() {
|
||||
local branch=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
if [[ "$branch" != master ]]; then
|
||||
>&2 echo "You can only publish from master."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Build the release images
|
||||
dc -br build
|
||||
|
||||
local patch_version=`grep -Po '(?<=version = ").*(?=")' Cargo.toml | head -n1`
|
||||
local major_version=`echo "$patch_version" | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1/'`
|
||||
local minor_version=`echo "$patch_version" | sed -E 's/([0-9]+).([0-9]+).([0-9]+)/\1.\2/'`
|
||||
local tags=("latest" "$patch_version" "$minor_version" "$major_version")
|
||||
|
||||
for tag in "${tags[@]}"; do
|
||||
# Create the tag
|
||||
docker tag "$image:$tags" "$image:$tag"
|
||||
|
||||
# Push the tag
|
||||
docker push "$image:$tag"
|
||||
|
||||
# Remove the tag again, if it's not the main tag
|
||||
[[ "$tag" != "$tags" ]] && docker rmi "$image:$tag"
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
# Entrypoint to the script
|
||||
#
|
||||
# $1: action to perform, defaults to 'build'
|
||||
# $2: binary to use, defaults to 'server'
|
||||
function main() {
|
||||
# Default values
|
||||
local cmd="${1:-build}"
|
||||
local bin="${2:-server}"
|
||||
|
||||
case $cmd in
|
||||
# Building
|
||||
b | build ) dcr build --bin "$bin" && dc -- logs -f app ;;
|
||||
br | build-release ) dc -br build ;;
|
||||
bf | build-frontend ) cd "$web_dir" && yarn run build ;;
|
||||
|
||||
# Running
|
||||
r | run ) dcr run --bin "$bin" && dc -- logs -f app ;;
|
||||
rr | run-release ) dc -br -- up --build --detach && dc -r -- logs -f app ;;
|
||||
rf | run-frontend ) dcr run --bin server && cd "$web_dir" && yarn run dev ;;
|
||||
s | stop ) dc down ;;
|
||||
sr | stop-release ) dc -r stop ;;
|
||||
|
||||
# Ease of life
|
||||
psql ) dc -- exec db psql -U fej -d fej ;;
|
||||
sh ) dc -- exec app sh ;;
|
||||
|
||||
# Misc
|
||||
docs ) cargo doc --no-deps ;;
|
||||
format ) cargo fmt ;;
|
||||
l | logs ) dc -- logs -f app ;;
|
||||
lint ) cargo fmt -- --check ;;
|
||||
p | push | publish ) publish ;;
|
||||
pb ) publish_builder ;;
|
||||
t | test ) dcr -- test --no-fail-fast && dc -- logs -f app ;;
|
||||
* ) >&2 echo "Invalid command."; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
|
@ -0,0 +1,6 @@
|
|||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
||||
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
|
@ -0,0 +1,36 @@
|
|||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
|
||||
|
||||
|
||||
-- Sets up a trigger for the given table to automatically set a column called
|
||||
-- `updated_at` whenever the row is modified (unless `updated_at` was included
|
||||
-- in the modified columns)
|
||||
--
|
||||
-- # Example
|
||||
--
|
||||
-- ```sql
|
||||
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
|
||||
--
|
||||
-- SELECT diesel_manage_updated_at('users');
|
||||
-- ```
|
||||
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
||||
BEGIN
|
||||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
||||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
IF (
|
||||
NEW IS DISTINCT FROM OLD AND
|
||||
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
||||
) THEN
|
||||
NEW.updated_at := current_timestamp;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
|
@ -0,0 +1,2 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
DROP table ivago_streets;
|
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE ivago_streets (
|
||||
name TEXT NOT NULL,
|
||||
city TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (name, city)
|
||||
);
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
# Roadmap
|
||||
|
||||
This file contains a listing of my current ideas/plans for this project. This
|
||||
could change at any minute, but it serves as a quick overview of my plans for
|
||||
the project.
|
||||
|
||||
## Ivago
|
||||
|
||||
### Summary
|
||||
|
||||
* Base project structure
|
||||
* RESTful wrapper around Ivago's API for showing the pickup calendar
|
||||
|
||||
### Description
|
||||
|
||||
Version 1.0 won't be a very big one, but it's important nonetheless. It
|
||||
contains a base project, on which I can build all the other modules. The only
|
||||
real feature it'll have is a wrapper around the Ivago API.
|
||||
|
||||
Ivago is one of the companies in Belgium that comes pick up the trash. On their
|
||||
site, you can view a calendar for your street displaying when they'll come pick
|
||||
up which kinds of trash. The sad part is that this site is very much not a
|
||||
RESTful API, relying on cookies to know which street & city you entered.
|
||||
|
||||
In one of my Web Development classes, I was given the assignment to convert
|
||||
this API into a RESTful one. I ended up fully wrapping it up using Python, so
|
||||
my goal is to port said code to Rust so we can then query my API for the same
|
||||
information their website would give. This allows us to remain anonymous while
|
||||
still collecting the same data. Furthermore, having the data available in
|
||||
computer-readable format opens up ways to write a custom frontend for the API
|
||||
(which I will be doing sometime in the near future).
|
||||
|
||||
## The Curse of the Forge
|
||||
|
||||
### Summary
|
||||
|
||||
* Curseforge site scraper
|
||||
* Easy lookup of download links for modpacks & their mods
|
||||
* Caching of Ivago API
|
||||
|
||||
### Description
|
||||
|
||||
Let's start off by saying I'm an avid Minecraft players. I still play at least
|
||||
once a week, even after almost 8 years of playing. I also love doing stuff on
|
||||
servers, so combining this two is quite easy: I host lots of Minecraft servers.
|
||||
These servers often run modpacks, to spice up the game. This is where the
|
||||
motvation for this version comes in.
|
||||
|
||||
The Curseforge website hosts *a lot* of modpacks, but sadly, they're not
|
||||
exactly in a computer-friendly format. Furthermore, the "server files" zips you
|
||||
often see included with a modpack just contain a yaml file, containing
|
||||
definitions for mods that only their launcher can use. I'm stubborn however,
|
||||
and refuse to use their launcher, as it doesn't work with my Docker-based setup
|
||||
scripts, and I just like doing things myself. Therefore, I want to do the
|
||||
following things:
|
||||
|
||||
* Periodically scrape their site for all modpacks
|
||||
* Store all the information I'll ever need in a database
|
||||
* Provide endpoints that can return a list of mods to download & the config
|
||||
directory
|
||||
|
||||
I could then possibly integrate my API into my own scripts, allowing me to spin
|
||||
up a modded Minecraft server from the command line, without having to ever
|
||||
touch their websites or services (besides downloading the mods of course).
|
||||
|
||||
As a bonus, I want to cache the Ivago API's calendars, considering I'll be
|
||||
setting up a database for this version anyways.
|
||||
|
||||
## Kissanime
|
||||
|
||||
I like watching anime from time to time, and I've always used Kissanime for
|
||||
this. However, their sites can be quite slow, and riddled with ads. That's why
|
||||
I'd like to create a high-speed wrapper that extracts all the needed info from
|
||||
their sites, removing the need for the user to ever actually visit their site.
|
||||
The API can just act as a fast search index, complete with indexing of the
|
||||
links to the videos and everything.
|
|
@ -1,17 +1,24 @@
|
|||
// I can probably do this way easier using an external crate, I should do that
|
||||
use rocket::http::Status;
|
||||
|
||||
/// Represents any general error that the API can encounter during execution.
|
||||
/// It allows us to more easily process errors, and hopefully allows for
|
||||
/// more clear error messages.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum FejError {
|
||||
InvalidArgument,
|
||||
FailedRequest,
|
||||
DatabaseError,
|
||||
}
|
||||
|
||||
// I'd love to move this over to the server binary, but right now, error E0117 is making that
|
||||
// imopssible
|
||||
impl From<FejError> for Status {
|
||||
fn from(err: FejError) -> Status {
|
||||
match err {
|
||||
FejError::InvalidArgument => Status::BadRequest,
|
||||
FejError::FailedRequest => Status::InternalServerError,
|
||||
FejError::DatabaseError => Status::InternalServerError,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,3 +35,9 @@ impl From<chrono::ParseError> for FejError {
|
|||
FejError::InvalidArgument
|
||||
}
|
||||
}
|
||||
|
||||
impl From<diesel::result::Error> for FejError {
|
||||
fn from(_: diesel::result::Error) -> FejError {
|
||||
FejError::DatabaseError
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
use crate::errors::FejError;
|
||||
use chrono::{DateTime, NaiveDate, TimeZone};
|
||||
use chrono_tz::Europe::Brussels;
|
||||
use chrono_tz::Tz;
|
||||
use rocket::http::RawStr;
|
||||
use rocket::request::FromFormValue;
|
||||
use serde::ser::Serializer;
|
||||
use serde::Serialize;
|
||||
use chrono_tz::{Europe::Brussels, Tz};
|
||||
use rocket::{http::RawStr, request::FromFormValue};
|
||||
use serde::{ser::Serializer, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// This class is a simple wrapper around chrono's DateTime. Its sole purpose
|
|
@ -0,0 +1,10 @@
|
|||
use super::Street;
|
||||
use crate::{errors::FejError, schema::ivago_streets::dsl::*};
|
||||
use {diesel::prelude::*, PgConnection};
|
||||
|
||||
pub fn search_streets(db_con: &PgConnection, search_term: &str) -> Result<Vec<Street>, FejError> {
|
||||
Ok(ivago_streets
|
||||
.filter(name.ilike(format!("%{}%", search_term)))
|
||||
.or_filter(city.ilike(format!("%{}%", search_term)))
|
||||
.load(db_con)?)
|
||||
}
|
|
@ -2,10 +2,13 @@ use crate::errors::FejError;
|
|||
use chrono::DateTime;
|
||||
use chrono_tz::Tz;
|
||||
use reqwest::blocking as reqwest;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::{From, TryFrom};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
convert::{From, TryFrom},
|
||||
};
|
||||
|
||||
mod basic_date;
|
||||
pub mod db;
|
||||
mod pickup_time;
|
||||
mod street;
|
||||
|
||||
|
@ -20,15 +23,14 @@ const BASE_URL: &str = "https://www.ivago.be/nl/particulier/afval/ophaling";
|
|||
/// Endpoint for the actual calendar output
|
||||
const CAL_URL: &str = "https://www.ivago.be/nl/particulier/garbage/pick-up/pickups";
|
||||
|
||||
/// Searches the Ivago API for streets in the given city
|
||||
/// Searches the Ivago API for streets in the given city.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `street` - name of the street
|
||||
/// * `city` - city the street is in
|
||||
pub fn search_streets(street_name: &str) -> Result<Vec<Street>, FejError> {
|
||||
/// * `search_term` - Search term to use to look for streets
|
||||
pub fn search_streets(search_term: &str) -> Result<Vec<Street>, FejError> {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.get(SEARCH_URL).query(&[("q", street_name)]).send()?;
|
||||
let response = client.get(SEARCH_URL).query(&[("q", search_term)]).send()?;
|
||||
let data: Vec<HashMap<String, String>> = response.json()?;
|
||||
|
||||
// This is pretty cool, filter_map first does get() on all the maps, and
|
||||
|
@ -41,14 +43,14 @@ pub fn search_streets(street_name: &str) -> Result<Vec<Street>, FejError> {
|
|||
.collect())
|
||||
}
|
||||
|
||||
/// Returns the pickup times for the various trash types
|
||||
/// Returns the pickup times for the various trash types.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `street` - desired street
|
||||
/// * `number` - house number
|
||||
/// * `start_date` - earliest date for the results
|
||||
/// * `end_date` - latest date for the results
|
||||
/// * `street` - Street to look up
|
||||
/// * `number` - House number in given street
|
||||
/// * `start_date` - Earliest date for the results
|
||||
/// * `end_date` - Latest date for the results
|
||||
pub fn get_pickup_times(
|
||||
street: &Street,
|
||||
number: &u32,
|
|
@ -1,19 +1,22 @@
|
|||
use super::BasicDate;
|
||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
|
||||
/// Represents a pickup time instance. All fields are a direct map of the
|
||||
/// original API
|
||||
/// Represents a date when a pickup will occur. Label describes which type of
|
||||
/// trash will be picked up.
|
||||
pub struct PickupTime {
|
||||
date: BasicDate,
|
||||
label: String,
|
||||
}
|
||||
|
||||
impl PickupTime {
|
||||
/// Creates a new PickupTime instance.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `date` - Date of pickup time
|
||||
/// * `label` - Type of trash
|
||||
pub fn new(date: BasicDate, label: String) -> PickupTime {
|
||||
PickupTime {
|
||||
date: date,
|
||||
label: label,
|
||||
}
|
||||
PickupTime { date, label }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
use crate::schema::ivago_streets;
|
||||
use diesel::{Insertable, Queryable};
|
||||
use regex::Regex;
|
||||
use rocket::http::RawStr;
|
||||
use rocket::request::FromFormValue;
|
||||
use rocket::{http::RawStr, request::FromFormValue};
|
||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Represents a street
|
||||
/// Represents a street in a given city
|
||||
#[derive(Queryable, Insertable)]
|
||||
#[table_name = "ivago_streets"]
|
||||
pub struct Street {
|
||||
name: String,
|
||||
city: String,
|
||||
|
@ -14,10 +17,7 @@ impl Street {
|
|||
// This constructor just makes my life a bit easier during testing
|
||||
#[cfg(test)]
|
||||
fn new(name: String, city: String) -> Street {
|
||||
Street {
|
||||
name: name,
|
||||
city: city,
|
||||
}
|
||||
Street { name, city }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ impl<'v> FromFormValue<'v> for Street {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Tests the conversion to string
|
||||
#[test]
|
||||
fn test_to_string() {
|
||||
let street = Street::new(String::from("testname"), String::from("city"));
|
|
@ -0,0 +1,10 @@
|
|||
#[macro_use]
|
||||
extern crate diesel;
|
||||
|
||||
// Route modules
|
||||
pub mod ivago;
|
||||
|
||||
// Helper modules
|
||||
pub mod errors;
|
||||
|
||||
pub mod schema;
|
|
@ -0,0 +1,6 @@
|
|||
table! {
|
||||
ivago_streets (name, city) {
|
||||
name -> Text,
|
||||
city -> Text,
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
# Ivago
|
||||
|
||||
This part of the API is a wrapper around the Ivago website (Ivago being the
|
||||
company that collects the trash in my city). Their site isn't exactly RESTful,
|
||||
so this endpoint simply wraps it in a RESTful wrapper.
|
|
@ -1,30 +0,0 @@
|
|||
mod controller;
|
||||
|
||||
use controller::{get_pickup_times, search_streets};
|
||||
use controller::{BasicDate, PickupTime, Street};
|
||||
use rocket::http::Status;
|
||||
use rocket_contrib::json::Json;
|
||||
|
||||
pub fn routes() -> Vec<rocket::Route> {
|
||||
routes![route_search_streets, route_get_pickup_times]
|
||||
}
|
||||
|
||||
#[get("/search?<street>")]
|
||||
pub fn route_search_streets(street: String) -> Result<Json<Vec<Street>>, Status> {
|
||||
Ok(Json(search_streets(street.as_str())?))
|
||||
}
|
||||
|
||||
#[get("/?<street>&<number>&<start_date>&<end_date>")]
|
||||
pub fn route_get_pickup_times(
|
||||
street: Street,
|
||||
number: u32,
|
||||
start_date: BasicDate,
|
||||
end_date: BasicDate,
|
||||
) -> Result<Json<Vec<PickupTime>>, Status> {
|
||||
Ok(Json(get_pickup_times(
|
||||
&street,
|
||||
&number,
|
||||
&start_date.0,
|
||||
&end_date.0,
|
||||
)?))
|
||||
}
|
11
src/lib.rs
11
src/lib.rs
|
@ -1,11 +0,0 @@
|
|||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
// Route modules
|
||||
pub mod ivago;
|
||||
|
||||
// Helper modules
|
||||
pub mod catchers;
|
||||
pub mod errors;
|
14
src/main.rs
14
src/main.rs
|
@ -1,14 +0,0 @@
|
|||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
use fej_lib::{catchers, ivago};
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite()
|
||||
.mount("/ivago", ivago::routes())
|
||||
.register(catchers![catchers::not_found])
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rocket().launch();
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
use diesel::{insert_into, Connection, PgConnection, RunQueryDsl};
|
||||
use fej::{ivago::search_streets, schema::ivago_streets::dsl::*};
|
||||
|
||||
const ABC: &str = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
fn main() {
|
||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
|
||||
let db_conn = PgConnection::establish(&database_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url));
|
||||
|
||||
// Doing this linearly is good enough I'd say
|
||||
for c in ABC.chars() {
|
||||
if let Ok(streets) = search_streets(&c.to_string()) {
|
||||
insert_into(ivago_streets)
|
||||
.values(streets)
|
||||
.execute(&db_conn)
|
||||
.expect("Failed to insert rows.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
#[macro_use]
|
||||
extern crate rocket_contrib;
|
||||
#[macro_use]
|
||||
extern crate diesel_migrations;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
mod catchers;
|
||||
mod routes;
|
||||
|
||||
// Very temporary solution for CORS
|
||||
// https://stackoverflow.com/questions/62412361/how-to-set-up-cors-or-options-for-rocket-rs
|
||||
use rocket::{
|
||||
fairing::{AdHoc, Fairing, Info, Kind},
|
||||
http::Header,
|
||||
Request, Response, Rocket,
|
||||
};
|
||||
use rocket_contrib::databases::diesel;
|
||||
#[cfg(feature = "frontend")]
|
||||
use rocket_contrib::serve::StaticFiles;
|
||||
|
||||
pub struct Cors;
|
||||
|
||||
impl Fairing for Cors {
|
||||
fn info(&self) -> Info {
|
||||
Info {
|
||||
name: "Add CORS headers to responses",
|
||||
kind: Kind::Response,
|
||||
}
|
||||
}
|
||||
|
||||
fn on_response(&self, _: &Request, response: &mut Response) {
|
||||
response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
|
||||
response.set_header(Header::new(
|
||||
"Access-Control-Allow-Methods",
|
||||
"POST, GET, PATCH, OPTIONS",
|
||||
));
|
||||
response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
|
||||
response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
|
||||
}
|
||||
}
|
||||
|
||||
// Macro from diesel_migrations that sets up migrations
|
||||
embed_migrations!();
|
||||
|
||||
// This defines a connection to the database
|
||||
#[database("postgres_fej")]
|
||||
pub struct FejDbConn(diesel::PgConnection);
|
||||
|
||||
// I'd like to thank Stackoverflow for helping me with this
|
||||
// https://stackoverflow.com/questions/61047355/how-to-run-diesel-migration-with-rocket-in-production
|
||||
fn run_db_migrations(rocket: Rocket) -> Result<Rocket, Rocket> {
|
||||
let conn = FejDbConn::get_one(&rocket).expect("database connection");
|
||||
match embedded_migrations::run(&*conn) {
|
||||
Ok(()) => Ok(rocket),
|
||||
Err(_) => Err(rocket),
|
||||
}
|
||||
}
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
// This needs to be muted for the frontend feature
|
||||
#[allow(unused_mut)]
|
||||
let mut rocket = rocket::ignite()
|
||||
.attach(Cors)
|
||||
.attach(FejDbConn::fairing())
|
||||
.attach(AdHoc::on_attach("Database Migrations", run_db_migrations))
|
||||
.mount("/api/ivago", routes::ivago()) // /api being hardcoded is temporary
|
||||
.register(catchers![catchers::not_found]);
|
||||
|
||||
// TODO make all of this not hard-coded
|
||||
#[cfg(feature = "frontend")]
|
||||
{
|
||||
rocket = rocket.mount("/", StaticFiles::from("/app/dist"));
|
||||
}
|
||||
|
||||
rocket
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rocket().launch();
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
use crate::FejDbConn;
|
||||
use fej::ivago::{db::search_streets, get_pickup_times, BasicDate, PickupTime, Street};
|
||||
use rocket::http::Status;
|
||||
use rocket_contrib::json::Json;
|
||||
|
||||
/// This route handles the Ivago search endpoint. It returns a list of streets,
|
||||
/// consisting of a street name & a city.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `search_term` - Search term to use to look for streets
|
||||
#[get("/search?<q>")]
|
||||
pub fn route_search_streets(db_conn: FejDbConn, q: String) -> Result<Json<Vec<Street>>, Status> {
|
||||
Ok(Json(search_streets(&db_conn.0, q.as_str())?))
|
||||
}
|
||||
|
||||
/// Handles returning of pickup times for a specific address. It returns a list
|
||||
/// of pickup times, containing a date and a description of the trash type.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `street` - Street to look up
|
||||
/// * `number` - House number in the given street
|
||||
/// * `start_date` - Earliest date that can be returned
|
||||
/// * `end_date` - Latest date that can be returned
|
||||
#[get("/?<street>&<number>&<start_date>&<end_date>")]
|
||||
pub fn route_get_pickup_times(
|
||||
street: Street,
|
||||
number: u32,
|
||||
start_date: BasicDate,
|
||||
end_date: BasicDate,
|
||||
) -> Result<Json<Vec<PickupTime>>, Status> {
|
||||
Ok(Json(get_pickup_times(
|
||||
&street,
|
||||
&number,
|
||||
&start_date.0,
|
||||
&end_date.0,
|
||||
)?))
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
mod ivago;
|
||||
|
||||
pub fn ivago() -> Vec<rocket::Route> {
|
||||
routes![ivago::route_search_streets, ivago::route_get_pickup_times]
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
/// In here, any non-unit tests are placed.
|
||||
use rocket::http::Status;
|
||||
use rocket::local::Client;
|
||||
use rocket::{http::Status, local::Client};
|
||||
|
||||
fn rocket() -> rocket::Rocket {
|
||||
rocket::ignite().mount("/", fej_lib::ivago::routes())
|
||||
rocket::ignite().mount("/", super::routes::ivago())
|
||||
}
|
||||
|
||||
/// Test 404 response
|
|
@ -0,0 +1 @@
|
|||
VITE_ENDPOINT=https://fej.roosens.me/api
|
|
@ -0,0 +1,15 @@
|
|||
env:
|
||||
browser: true
|
||||
es2021: true
|
||||
extends:
|
||||
- 'plugin:vue/essential'
|
||||
- standard
|
||||
parserOptions:
|
||||
ecmaVersion: 12
|
||||
parser: '@typescript-eslint/parser'
|
||||
sourceType: module
|
||||
plugins:
|
||||
- vue
|
||||
- '@typescript-eslint'
|
||||
rules:
|
||||
indent: ["error", 4]
|
|
@ -0,0 +1,130 @@
|
|||
# Created by https://www.toptal.com/developers/gitignore/api/node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
.env*.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Storybook build outputs
|
||||
.out
|
||||
.storybook-out
|
||||
storybook-static
|
||||
|
||||
# rollup.js default build output
|
||||
dist/
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# Temporary folders
|
||||
tmp/
|
||||
temp/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/node
|
|
@ -0,0 +1,27 @@
|
|||
# Vue 3 + Typescript + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 and Typescript in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur). Make sure to enable `vetur.experimental.templateInterpolationService` in settings!
|
||||
|
||||
### If Using `<script setup>`
|
||||
|
||||
[`<script setup>`](https://github.com/vuejs/rfcs/pull/227) is a feature that is currently in RFC stage. To get proper IDE support for the syntax, use [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) instead of Vetur (and disable Vetur).
|
||||
|
||||
## Type Support For `.vue` Imports in TS
|
||||
|
||||
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can use the following:
|
||||
|
||||
### If Using Volar
|
||||
|
||||
Run `Volar: Switch TS Plugin on/off` from VSCode command palette.
|
||||
|
||||
### If Using Vetur
|
||||
|
||||
1. Install and add `@vuedx/typescript-plugin-vue` to the [plugins section](https://www.typescriptlang.org/tsconfig#plugins) in `tsconfig.json`
|
||||
2. Delete `src/shims-vue.d.ts` as it is no longer needed to provide module info to Typescript
|
||||
3. Open `src/main.ts` in VSCode
|
||||
4. Open the VSCode command palette
|
||||
5. Search and run "Select TypeScript version" -> "Use workspace version"
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Fej</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "fej-frontend",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"format": "yarn run lint --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.0.5",
|
||||
"vue-router": "^4.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||
"@typescript-eslint/parser": "^4.22.0",
|
||||
"@vitejs/plugin-vue": "^1.2.1",
|
||||
"@vue/compiler-sfc": "^3.0.5",
|
||||
"eslint": "^8.0.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.0.0",
|
||||
"eslint-plugin-vue": "^7.9.0",
|
||||
"typescript": "^4.1.3",
|
||||
"vite": "^2.2.1",
|
||||
"vue-tsc": "^0.1.0"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div>
|
||||
<Nav />
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import Nav from './components/Nav.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
components: {
|
||||
Nav
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,18 @@
|
|||
export interface Street {
|
||||
name: string
|
||||
city: string
|
||||
}
|
||||
|
||||
export async function search (searchTerm: string): Promise<Street[]> {
|
||||
const baseURL = import.meta.env.VITE_ENDPOINT as string
|
||||
|
||||
const r = await fetch(`${baseURL}/ivago/search?` + new URLSearchParams({
|
||||
q: searchTerm
|
||||
}))
|
||||
|
||||
if (!r.ok) {
|
||||
return Promise.reject()
|
||||
}
|
||||
|
||||
return r.json()
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
|
@ -0,0 +1,15 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1>Fej</h1>
|
||||
<p>Welcome to Fej, my frontend/backend combo.</p>
|
||||
<p>If you can see this, the cicd worked!</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Home'
|
||||
})
|
||||
</script>
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1>Ivago</h1>
|
||||
<input
|
||||
v-model="query"
|
||||
v-on:keyup.enter="search"
|
||||
type="text"
|
||||
placeholder="Street..." />
|
||||
<div id="scroll-list">
|
||||
<ul v-if="msg === ''">
|
||||
<li
|
||||
v-for="item in items"
|
||||
v-bind:key="`${item.name} (${item.city})`" >
|
||||
{{ item.name }} ({{ item.city }})
|
||||
</li>
|
||||
</ul>
|
||||
<p v-else>{{ msg }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { Street, search as ivagoSearch } from '../api/ivago'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Ivago',
|
||||
data () {
|
||||
return {
|
||||
items: [] as Street[],
|
||||
msg: '',
|
||||
query: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search () {
|
||||
this.items = []
|
||||
this.msg = 'Loading...'
|
||||
|
||||
if (this.query === '') {
|
||||
this.msg = ''
|
||||
return
|
||||
}
|
||||
|
||||
ivagoSearch(this.query)
|
||||
.then((res: Street[]) => {
|
||||
this.items = res
|
||||
this.msg = ''
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#scroll-list {
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,43 @@
|
|||
<template>
|
||||
<div id="menu-wrapper">
|
||||
<nav id="menu">
|
||||
<router-link to="/">Home</router-link>
|
||||
<router-link to="/ivago">Ivago</router-link>
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Nav'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#menu-wrapper {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 150px;
|
||||
background-color: #242624;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#menu {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
#menu > a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
color: #5f635f;
|
||||
text-decoration: none;
|
||||
}
|
||||
#menu > a:hover {
|
||||
color: #c2ccc1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,8 @@
|
|||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
|
@ -0,0 +1,21 @@
|
|||
import { createWebHistory, createRouter } from 'vue-router'
|
||||
import Home from './components/Home.vue'
|
||||
import Ivago from './components/Ivago.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/ivago',
|
||||
component: Ivago
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
|
@ -0,0 +1,5 @@
|
|||
declare module '*.vue' {
|
||||
import { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext", "dom"],
|
||||
"types": ["vite/client"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()]
|
||||
})
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue