Compare commits

..

1 Commits

Author SHA1 Message Date
Jef Roosens 53334fd56f
Merge branch 'develop' 2021-04-17 21:44:49 +02:00
49 changed files with 116 additions and 4527 deletions

View File

@ -1,42 +1,20 @@
*
# =====BACKEND=====
## Source code
# Source code
!src/
## Cargo files
# Cargo files
!Cargo.toml
!Cargo.lock
## Entrypoint for devop container
# Entrypoint for devop container
!docker/entrypoint_dev.sh
!docker/entrypoint.sh
## Config file
# Config file
!Rocket.toml
## Database migrations
# 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

View File

@ -1,7 +0,0 @@
root = true
[*]
end_of_line = lf
insert_final_newline = false
indent_style = space
indent_size = 4

View File

@ -1,91 +0,0 @@
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 ]

56
Cargo.lock generated
View File

@ -58,9 +58,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "0.7.18"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
@ -98,6 +98,12 @@ 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"
@ -317,9 +323,9 @@ dependencies = [
[[package]]
name = "diesel"
version = "1.4.8"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d"
checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542"
dependencies = [
"bitflags",
"byteorder",
@ -855,9 +861,9 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "memchr"
version = "2.4.0"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "migrations_internals"
@ -1336,9 +1342,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.5.4"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
@ -1347,9 +1353,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.25"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "remove_dir_all"
@ -1400,12 +1406,12 @@ dependencies = [
[[package]]
name = "rocket"
version = "0.4.10"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a7ab1dfdc75bb8bd2be381f37796b1b300c45a3c9145b34d86715e8dd90bf28"
checksum = "7febfdfd4d43facfc7daba20349ebe2c310c6735bd6a2a9255ea8bc425b4cb13"
dependencies = [
"atty",
"base64 0.13.0",
"base64 0.12.3",
"log 0.4.14",
"memchr",
"num_cpus",
@ -1421,9 +1427,9 @@ dependencies = [
[[package]]
name = "rocket_codegen"
version = "0.4.10"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1729e687d6d2cf434d174da84fb948f7fef4fac22d20ce94ca61c28b72dbcf9f"
checksum = "ceac2c55b2c8b1cdc53add64332defa5fc227f64263b86b4114d1386286d42a3"
dependencies = [
"devise",
"glob",
@ -1436,9 +1442,9 @@ dependencies = [
[[package]]
name = "rocket_contrib"
version = "0.4.10"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b6303dccab46dce6c7ac26c9b9d8d8cde1b19614b027c3f913be6611bff6d9b"
checksum = "d7954a707f9ca18aa74ca8c1f5d1f900f52a4dceb68e96e3112143f759cfd20e"
dependencies = [
"diesel",
"log 0.4.14",
@ -1452,9 +1458,9 @@ dependencies = [
[[package]]
name = "rocket_contrib_codegen"
version = "0.4.10"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0f2cbcb6c09b3ac0acdf77682ff8c9d1f317361498a773ee50b32be7fddfe2b"
checksum = "30deb6dec53b91fac3538a2a3935cf13e0f462745f9f33bf27bedffbe7265b5d"
dependencies = [
"devise",
"quote 0.6.13",
@ -1464,9 +1470,9 @@ dependencies = [
[[package]]
name = "rocket_http"
version = "0.4.10"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6131e6e6d38a9817f4a494ff5da95971451c2eb56a53915579fc9c80f6ef0117"
checksum = "ce364100ed7a1bf39257b69ebd014c1d5b4979b0d365d8c9ab0aa9c79645493d"
dependencies = [
"cookie 0.11.4",
"hyper 0.10.16",
@ -1574,18 +1580,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.126"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.126"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
dependencies = [
"proc-macro2 1.0.26",
"quote 1.0.9",

View File

@ -4,10 +4,6 @@ version = "1.0.2"
authors = ["Jef Roosens <roosensjef@gmail.com>"]
edition = "2018"
[features]
# Enables hosting of the frontend
frontend = []
[lib]
name = "fej"
path = "src/fej/lib.rs"
@ -23,26 +19,18 @@ 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.10"
serde = "1.0.126"
rocket = "0.4.7"
serde = "1.0.124"
chrono = "0.4.19"
chrono-tz = "0.5.3"
regex = "1.5.4"
reqwest = { version = "0.11.3", features = ["blocking", "json", "cookies"] }
diesel = { version = "1.4.8", features = ["postgres"] }
regex = "1.4.5"
reqwest = { version = "0.11.2", features = ["blocking", "json", "cookies"] }
diesel = { version = "1.4.6", features = ["postgres"] }
diesel_migrations = "1.4.0"
[dependencies.rocket_contrib]
version = "0.4.10"
version = "0.4.7"
default-features = false
features = ["json", "diesel_postgres_pool", "serve"]
features = ["json", "diesel_postgres_pool"]

View File

@ -2,4 +2,4 @@
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/fej/schema.rs"
file = "src/schema.rs"

View File

@ -1,8 +1,8 @@
# vim: filetype=dockerfile
# Our entire toolchain runs in alpine
FROM alpine:3.13.5 AS builder
FROM alpine:latest AS builder
ENV PATH "$PATH:/root/.cargo/bin"
ENV PATH "$PATH:/app/.cargo/bin"
# Needed for proper compiling of openssl-dev
ENV RUSTFLAGS "-C target-feature=-crt-static"
@ -19,7 +19,18 @@ RUN addgroup -S builder && \
openssl-dev \
postgresql-dev
# Switch to the non-root user
USER builder
WORKDIR /app
# 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
rustup target add x86_64-unknown-linux-musl --toolchain nightly && \
mkdir -p .cargo/registry target
# 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/

View File

@ -3,10 +3,6 @@ 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

View File

@ -1,9 +1,5 @@
# 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/
FROM chewingbever/fej-builder:latest AS builder
# And then finally, build the project
# Thank the lords that this article exists
@ -19,22 +15,11 @@ COPY --chown=builder:builder migrations/ ./migrations/
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
--target x86_64-unknown-linux-musl
# Now, we create the actual image
FROM alpine:3.13.5
FROM alpine:latest
COPY ./docker/crontab /var/spool/cron/crontabs/fej
# Install some dynamic libraries needed for everything to work
@ -52,9 +37,8 @@ RUN apk update && \
# 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
# Copy binary over to final image
COPY --from=builder --chown=fej:fej /app/output/bin /app/bin
# Embed config file inside container
# The workdir is changed so that the config file is read properly

View File

@ -1,2 +1 @@
# Runs the ivago scraper
*/30 * * * * /app/bin/populate_ivago
# This'll be filled up later

View File

@ -13,7 +13,7 @@ services:
- 'DATABASE_URL=postgres://fej:fej@db:5432/fej'
db:
image: 'postgres:14-alpine'
image: 'postgres:13-alpine'
restart: 'always'
environment:

26
fejctl
View File

@ -1,7 +1,6 @@
#!/usr/bin/env bash
image='chewingbever/fej'
web_dir='web'
# Small wrapper around the docker-compose command
#
@ -19,6 +18,16 @@ function dc() {
done
shift $((OPTIND-1))
if [[ "$build_builder" -eq 1 ]]; then
# We always rebuild the builder before we run any compose command
DOCKER_BUILDKIT=1 docker build \
-f docker/Dockerfile.builder \
-t "$image-builder:latest" . || {
>&2 echo "Failed to build builder.";
exit 1;
}
fi
if [[ "$release" -eq 1 ]]; then
DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1 docker-compose \
--file docker/docker-compose.yml \
@ -44,18 +53,6 @@ function dcr() {
--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`
@ -99,12 +96,10 @@ function main() {
# 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 ;;
@ -118,7 +113,6 @@ function main() {
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

View File

View File

@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql`
DROP table ivago_streets;
DROP SCHEMA ivago CASCADE;

View File

@ -1,4 +1,7 @@
CREATE TABLE ivago_streets (
-- Your SQL goes here
CREATE SCHEMA ivago;
CREATE TABLE ivago.streets (
name TEXT NOT NULL,
city TEXT NOT NULL,

View File

@ -1,3 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

View File

@ -8,7 +8,6 @@ use rocket::http::Status;
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
@ -18,7 +17,6 @@ impl From<FejError> for Status {
match err {
FejError::InvalidArgument => Status::BadRequest,
FejError::FailedRequest => Status::InternalServerError,
FejError::DatabaseError => Status::InternalServerError,
}
}
}
@ -35,9 +33,3 @@ impl From<chrono::ParseError> for FejError {
FejError::InvalidArgument
}
}
impl From<diesel::result::Error> for FejError {
fn from(_: diesel::result::Error) -> FejError {
FejError::DatabaseError
}
}

View File

@ -1,8 +1,11 @@
use crate::errors::FejError;
use chrono::{DateTime, NaiveDate, TimeZone};
use chrono_tz::{Europe::Brussels, Tz};
use rocket::{http::RawStr, request::FromFormValue};
use serde::{ser::Serializer, Serialize};
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 std::convert::TryFrom;
/// This class is a simple wrapper around chrono's DateTime. Its sole purpose

View File

@ -1,10 +0,0 @@
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)?)
}

View File

@ -2,13 +2,10 @@ use crate::errors::FejError;
use chrono::DateTime;
use chrono_tz::Tz;
use reqwest::blocking as reqwest;
use std::{
collections::HashMap,
convert::{From, TryFrom},
};
use std::collections::HashMap;
use std::convert::{From, TryFrom};
mod basic_date;
pub mod db;
mod pickup_time;
mod street;

View File

@ -16,7 +16,10 @@ impl PickupTime {
/// * `date` - Date of pickup time
/// * `label` - Type of trash
pub fn new(date: BasicDate, label: String) -> PickupTime {
PickupTime { date, label }
PickupTime {
date: date,
label: label,
}
}
}

View File

@ -1,13 +1,10 @@
use crate::schema::ivago_streets;
use diesel::{Insertable, Queryable};
use regex::Regex;
use rocket::{http::RawStr, request::FromFormValue};
use rocket::http::RawStr;
use rocket::request::FromFormValue;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::convert::TryFrom;
/// Represents a street in a given city
#[derive(Queryable, Insertable)]
#[table_name = "ivago_streets"]
pub struct Street {
name: String,
city: String,
@ -17,7 +14,10 @@ impl Street {
// This constructor just makes my life a bit easier during testing
#[cfg(test)]
fn new(name: String, city: String) -> Street {
Street { name, city }
Street {
name: name,
city: city,
}
}
}

View File

@ -1,10 +1,7 @@
#[macro_use]
extern crate diesel;
#![feature(proc_macro_hygiene, decl_macro)]
// Route modules
pub mod ivago;
// Helper modules
pub mod errors;
pub mod schema;

View File

@ -1,6 +0,0 @@
table! {
ivago_streets (name, city) {
name -> Text,
city -> Text,
}
}

View File

@ -1,21 +0,0 @@
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
src/schema.rs 100644
View File

View File

@ -15,18 +15,15 @@ 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::fairing::AdHoc;
use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header;
use rocket::{Request, Response, Rocket};
use rocket_contrib::databases::diesel;
#[cfg(feature = "frontend")]
use rocket_contrib::serve::StaticFiles;
pub struct Cors;
pub struct CORS;
impl Fairing for Cors {
impl Fairing for CORS {
fn info(&self) -> Info {
Info {
name: "Add CORS headers to responses",
@ -50,7 +47,7 @@ embed_migrations!();
// This defines a connection to the database
#[database("postgres_fej")]
pub struct FejDbConn(diesel::PgConnection);
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
@ -58,27 +55,17 @@ 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),
Err(e) => 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)
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
.mount("/ivago", routes::ivago())
.register(catchers![catchers::not_found])
}
fn main() {

View File

@ -1,5 +1,4 @@
use crate::FejDbConn;
use fej::ivago::{db::search_streets, get_pickup_times, BasicDate, PickupTime, Street};
use fej::ivago::{get_pickup_times, search_streets, BasicDate, PickupTime, Street};
use rocket::http::Status;
use rocket_contrib::json::Json;
@ -10,8 +9,8 @@ use rocket_contrib::json::Json;
///
/// * `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())?))
pub fn route_search_streets(q: String) -> Result<Json<Vec<Street>>, Status> {
Ok(Json(search_streets(q.as_str())?))
}
/// Handles returning of pickup times for a specific address. It returns a list

View File

@ -1,5 +1,6 @@
/// In here, any non-unit tests are placed.
use rocket::{http::Status, local::Client};
use rocket::http::Status;
use rocket::local::Client;
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/", super::routes::ivago())

View File

@ -1 +0,0 @@
VITE_ENDPOINT=http://localhost:8000/api

View File

@ -1 +0,0 @@
VITE_ENDPOINT=https://fej.roosens.me/api

View File

@ -1,15 +0,0 @@
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]

130
web/.gitignore vendored
View File

@ -1,130 +0,0 @@
# 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

View File

@ -1,27 +0,0 @@
# 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"

View File

@ -1,13 +0,0 @@
<!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>

View File

@ -1,30 +0,0 @@
{
"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.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,29 +0,0 @@
<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>

View File

@ -1,18 +0,0 @@
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.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,15 +0,0 @@
<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>

View File

@ -1,61 +0,0 @@
<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>

View File

@ -1,43 +0,0 @@
<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>

View File

@ -1,8 +0,0 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')

View File

@ -1,21 +0,0 @@
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

View File

@ -1,5 +0,0 @@
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

View File

@ -1,15 +0,0 @@
{
"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"]
}

View File

@ -1,7 +0,0 @@
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