Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
archeoss committed Oct 19, 2023
1 parent 9886e3b commit 3ee5fb5
Show file tree
Hide file tree
Showing 25 changed files with 2,231 additions and 703 deletions.
5 changes: 4 additions & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ thiserror = "1.0"
## General
tokio = { version = "1.32", features = ["rt", "macros", "rt-multi-thread" ] }
hyper = { version = "0.14", features = ["http2", "client"] }
nutype = { version = "0.3", features = ["serde", "regex"] }
prae = { version = "0.8", features = ["serde"] }
lazy_static = "1.4"
regex = "1.10"
serde = { version = "1.0", features = ["derive"] }
Expand All @@ -59,6 +59,9 @@ cli = { path = "../cli" }
## Frontend
frontend = { path = "../frontend", optional = true }

## Transpiling
tsync = "2.0"

[features]
default = [ "swagger", "frontend-bundle" ]
swagger = [ "dep:utoipa", "dep:utoipa-swagger-ui" , "dep:utoipa-redoc", "dep:utoipa-rapidoc" ]
Expand Down
11 changes: 7 additions & 4 deletions backend/src/connector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use axum::headers::{authorization::Basic, Authorization};
use error_stack::ResultExt;
use frunk::hlist;
use hyper::StatusCode;
use prae::Wrapper;
use std::{collections::HashMap, sync::Arc};
use thiserror::Error;

Expand Down Expand Up @@ -132,7 +133,8 @@ impl BobClient {

let context: ClientContext = hlist![timeout, auth, XSpanIdString::default()];
let client = Box::new(
Client::try_new_http(&hostname.to_string()).change_context(ClientError::InitClient)?,
Client::try_new_http(&hostname.get().to_string())
.change_context(ClientError::InitClient)?,
);
let nodes = client
.with_context(context.clone())
Expand All @@ -158,11 +160,11 @@ impl BobClient {
}
hostname
.ok()
.map(|hostname| (name, Client::try_new_http(&hostname.to_string())))
.map(|hostname| (name, Client::try_new_http(&hostname.get().to_string())))
})
.filter_map(|(name, client)| {
if client.is_err() {
tracing::warn!("couldn't create client for {hostname}");
tracing::warn!("couldn't create client for {}", hostname.get());
}
client.ok().map(|client| {
(
Expand All @@ -173,7 +175,8 @@ impl BobClient {
})
.collect();
let client = Box::new(
Client::try_new_http(&hostname.to_string()).change_context(ClientError::InitClient)?,
Client::try_new_http(&hostname.get().to_string())
.change_context(ClientError::InitClient)?,
);
Ok(Self {
hostname: bob_data.hostname,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub mod services;
#[cfg_attr(all(feature = "swagger", debug_assertions), openapi(
paths(root, services::auth::login, services::auth::logout),
components(
schemas(models::shared::Credentials, models::shared::HostnameApi, models::shared::BobConnectionData)
schemas(models::shared::Credentials, models::shared::Hostname, models::shared::BobConnectionData)
),
tags(
(name = "bob", description = "BOB management API")
Expand Down
9 changes: 6 additions & 3 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![allow(clippy::multiple_crate_versions)]

use axum::Router;

use axum::{Extension, Router};
use axum_login::{memory_store::MemoryStore as AuthMemoryStore, AuthLayer};
use axum_sessions::async_session::MemoryStore as SessionMemoryStore;
use axum_sessions::SessionLayer;
use backend::models::shared::RequestTimeout;
use backend::router::{NoApi, RouterApiExt};
use backend::services::auth::SocketBobMemoryStore;
use backend::{config::ConfigExt, prelude::*, root, services::api_router};
Expand Down Expand Up @@ -42,7 +42,10 @@ async fn main() -> Result<(), AppError> {

let app = router(cors);
#[cfg(all(feature = "swagger", debug_assertions))]
let app = app.merge(backend::openapi_doc());
let app = app.merge(backend::openapi_doc())
.layer(Extension(RequestTimeout::from_millis(
config.request_timeout.as_millis() as u64,
)));

axum::Server::bind(&addr)
.serve(app.into_make_service())
Expand Down
27 changes: 18 additions & 9 deletions backend/src/models/shared.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
use nutype::nutype;
use lazy_static::lazy_static;
use prae::{ConstructionError, Wrapper};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{net::SocketAddr, time::Duration};
use tsync::tsync;
use utoipa::{IntoParams, ToSchema};

#[nutype(sanitize(trim, lowercase) validate(not_empty, regex = r"(https?)?(?::[\/]{2})?([^\:]+):(([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$)"))]
#[derive(Display, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Hostname(String);
// #[nutype(sanitize(trim, lowercase) validate(not_empty, regex = r"(https?)?(?::[\/]{2})?([^\:]+):(([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$)"))]
lazy_static! {
static ref HOSTNAME_REGEX: Regex = Regex::new(r"^(https?)?(?::[\/]{2})?([^\:]+):(([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$)$").unwrap();
}

#[derive(ToSchema)]
#[schema(as = Hostname)]
pub struct HostnameApi(String);
prae::define! {
#[derive(ToSchema, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub Hostname: String;
adjust |host| *host = host.trim().to_owned();
ensure |host| !host.is_empty() && HOSTNAME_REGEX.is_match(host);
}

impl Hostname {
/// Can be safely unwraped thanks to regex
Expand All @@ -27,7 +34,7 @@ impl Hostname {
}

impl TryFrom<SocketAddr> for Hostname {
type Error = HostnameError;
type Error = ConstructionError<Self>;

fn try_from(value: SocketAddr) -> Result<Self, Self::Error> {
Self::new(value.to_string())
Expand All @@ -38,11 +45,12 @@ impl TryFrom<Hostname> for SocketAddr {
type Error = std::net::AddrParseError;

fn try_from(value: Hostname) -> Result<Self, Self::Error> {
value.to_string().parse()
value.get().to_string().parse()
}
}

/// Data needed to connect to a BOB cluster
#[tsync]
#[derive(
IntoParams, ToSchema, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
Expand All @@ -57,6 +65,7 @@ pub struct BobConnectionData {
}

/// Optional auth credentials for a BOB cluster
#[tsync]
#[derive(
ToSchema, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
)]
Expand Down
20 changes: 20 additions & 0 deletions frontend/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,30 @@ module.exports = {
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
'plugin:astro/recommended', //
],
plugins: ['react-refresh'],
ignorePatterns: ['dist', '.eslintrc.cjs'],
rules: {
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
// overrides: [
// {
// // Define the configuration for `.astro` file.
// files: ['*.astro'],
// // Allows Astro components to be parsed.
// parser: 'astro-eslint-parser',
// // Parse the script in `.astro` as TypeScript by adding the following configuration.
// // It's the setting you need when using TypeScript.
// parserOptions: {
// parser: '@typescript-eslint/parser',
// extraFileExtensions: ['.astro'],
// },
// rules: {
// // override/add rules settings here, such as:
// // "astro/no-set-html-directive": "error"
// },
// },
// // ...
// ],
};
2 changes: 1 addition & 1 deletion frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repository.workspace = true

[lib]
name = "frontend"
path = "frontend.rs"
path = "/dev/null"
crate-type = ["lib"]

[build-dependencies]
Expand Down
5 changes: 2 additions & 3 deletions frontend/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';

import tailwind from '@astrojs/tailwind';

// https://astro.build/config
export default defineConfig({
integrations: [react(), tailwind()],
outDir: './frontend',
integrations: [react(), tailwind()],
outDir: './frontend',
});
3 changes: 3 additions & 0 deletions frontend/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ pub fn build_types() {
let mut inputs = vec![PathBuf::from(env!("CARGO_MANIFEST_DIR"))];
let mut output = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
inputs[0].pop();
inputs.push(inputs[0].clone());

inputs[0].push("backend");
inputs[1].push("frontend");
inputs[1].push("frontend.rs");
output.push("src/types/rust.d.ts");

tsync::generate_typescript_defs(inputs, output, false);
Expand Down
3 changes: 3 additions & 0 deletions frontend/frontend.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
// Some structs that must be redefined for transpiling without changing actual types on backend

#[tsync]
pub type Hostname = String;
78 changes: 45 additions & 33 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
{
"name": "bob-management-frontend",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro check && tsc --noEmit && astro build",
"preview": "astro preview",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^3.0.0",
"@astrojs/tailwind": "^5.0.0",
"@astrojs/check": "^0.2.0",
"@playwright/test": "^1.30.0",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"astro": "^3.0.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"tailwindcss": "^3.0.24",
"typescript": "^5.2.2",
"vite": "^4.4.9"
},
"devDependencies": {
"eslint": "^8.48.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"prettier": "^3.0.2"
}
"name": "bob-management-frontend",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro check && tsc --noEmit && astro build",
"preview": "astro preview",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.2.0",
"@astrojs/react": "^3.0.0",
"@astrojs/tailwind": "^5.0.0",
"@astrojs/ts-plugin": "^1.2.0",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.0",
"@mui/material": "^5.14.0",
"@mui/x-data-grid": "^6.16.2",
"@playwright/test": "^1.30.0",
"@types/material-ui": "^0.21.12",
"@types/mui-image": "^1.0.2",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
"astro": "^3.0.2",
"mui-image": "^1.0.7",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"tailwindcss": "^3.0.24",
"typescript": "^5.2.2",
"vite": "^4.4.9"
},
"devDependencies": {
"@typescript-eslint/parser": "^6.7.5",
"eslint": "^8.51.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-astro": "^0.29.1",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"prettier": "^3.0.2"
}
}
3 changes: 3 additions & 0 deletions frontend/public/brandmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 3ee5fb5

Please sign in to comment.