Feature Parity with python variant

This commit is contained in:
Neshura 2023-08-25 03:42:19 +02:00
parent 83bf813bb1
commit e19187d6c7
Signed by: Neshura
GPG key ID: B6983AAA6B9A7A6C
11 changed files with 3585 additions and 1 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/target
config.toml

2632
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

20
Cargo.toml Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "chellaris-rust-api"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4.3.1"
chrono = "0.4.26"
ctrlc = "3.4.0"
env_logger = "0.10.0"
schemars = "0.8.10"
serde = { version = "1.0.185", features = ["derive"] }
serde_json = "1.0.105"
sqlx = { version = "0.7.1", features = ["postgres", "runtime-tokio"] }
tokio = { version = "1.32.0", features = ["rt"] }
toml = "0.7.6"
utoipa = { version = "3.5.0", features = ["actix_extras", "non_strict_integers"] }
utoipa-swagger-ui = { version = "3.1.5", features = ["actix-web"] }

View file

@ -1 +0,0 @@
# chellaris-rust-api

5
package.json Normal file
View file

@ -0,0 +1,5 @@
{
"dependencies": {
"sqlx": "^4.3.2"
}
}

21
src/db/mod.rs Normal file
View file

@ -0,0 +1,21 @@
use std::error::Error;
use sqlx::{Postgres, postgres::PgConnectOptions, PgPool, Pool};
use crate::{PostgresConfig};
pub(crate) mod schemas;
pub(crate) async fn connect_postgres(config: PostgresConfig) -> Result<Pool<Postgres>, Box<dyn Error>> {
let connection_settings = PgConnectOptions::new()
.host(&config.host)
.port(config.port)
.username(&config.user)
.password(&config.password)
.database(&config.db);
let pool = PgPool::connect_with(connection_settings).await?;
return Ok(pool);
}

57
src/db/schemas.rs Normal file
View file

@ -0,0 +1,57 @@
use serde::Serialize;
use sqlx::FromRow;
use utoipa::ToSchema;
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct PortraitGroup {
pub id: i32,
pub name: String,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Portrait {
pub id: i32,
pub group_id: i32,
pub hires: String,
pub lores: Option<String>,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Game {
pub id: i32,
pub name: String,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct GameGroup {
pub id: i32,
pub game_id: i32,
pub name: String,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Ethic {
pub id: i32,
pub name: String,
pub machine_ethic: bool,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Empire {
pub id: i32,
pub discord_user: Option<String>,
pub group_id: i32,
pub gestalt: Option<bool>, // TODO: make nn in DB schema
pub empire_portrait_id: i32,
pub empire_portrait_group_id: i32,
pub group_game_id: i32,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct EmpireEthic {
pub empires_id: i32,
pub empires_group_id: i32,
pub empires_group_game_id: i32,
pub ethics_id: i32,
pub ethics_fanatic: bool,
}

211
src/main.rs Normal file
View file

@ -0,0 +1,211 @@
use std::{error::Error, fs, net::Ipv4Addr, net::Ipv6Addr, thread, time::Duration, sync::{Mutex, Arc, atomic::{AtomicBool, Ordering}}};
use chrono::Local;
use actix_web::{middleware::Logger, web, App, HttpServer, Result};
use serde::{Deserialize, Serialize};
use sqlx::{PgPool, Pool, Postgres, Connection};
use utoipa::OpenApi;
use utoipa_swagger_ui::{Config, SwaggerUi, Url};
use crate::db::connect_postgres;
mod db;
mod v2;
macro_rules! api_base {
() => {
"/api"
};
}
macro_rules! api_base_2 {
() => {
"/api/v2"
};
}
macro_rules! api_base_3 {
() => {
"/api/v3"
};
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub(crate) struct ConfigToml {
database: PostgresConfig,
auth: AuthenticationTokens,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub(crate) struct PostgresConfig {
host: String,
port: u16,
user: String,
password: String,
db: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub(crate) struct AuthenticationTokens {
moderator: String,
admin: String
}
pub struct AppState {
db: Pool<Postgres>,
auth_tokens: AuthenticationTokens,
}
async fn postgres_watchdog(pool: PgPool, is_alive: Arc<AtomicBool>, shutdown: Arc<AtomicBool>) {
loop {
if shutdown.load(Ordering::Relaxed) {
break;
}
let start = Local::now();
let mut conn = match pool.acquire().await {
Ok(data) => data,
Err(_) => break,
};
match conn.ping().await {
Ok(_) => {eprintln!("Pinged DB Server at {}", Local::now().format("%H:%M:%S"))},
Err(_) => todo!(),
};
let passed = (Local::now() - start).to_std().expect(&format!("Unable to get Time Difference for '{}' and '{}'", start, Local::now()));
thread::sleep(Duration::from_secs(15) - passed);
}
is_alive.store(false, Ordering::Relaxed);
}
#[actix_web::main]
async fn main() -> Result<()> {
env_logger::init();
let shutdown: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
let shutdown_clone = Arc::clone(&shutdown);
ctrlc::set_handler(move || {
eprintln!("Ctrl-C received");
shutdown_clone.store(true, Ordering::Relaxed)
})
.expect("Error setting Ctrl-C handler");
let toml_str = fs::read_to_string("config.toml").expect("Failed to read config.toml");
let config: ConfigToml = toml::from_str(&toml_str).expect("Failed to parse config.toml");
#[derive(OpenApi)]
#[openapi(
paths(
v2::empire_ethics,
v2::empires,
v2::ethics,
v2::game_groups,
v2::games,
v2::portrait_groups,
v2::portraits
),
components(schemas(
v2::schemas::PortraitGroup,
v2::schemas::Portrait,
v2::schemas::Ethic,
v2::schemas::Empire,
v2::schemas::EmpireEthic,
v2::schemas::Game,
v2::schemas::GameGroup
))
)]
struct ApiDocV2;
#[derive(OpenApi)]
#[openapi(paths(), components(schemas()))]
struct ApiDocV3;
let openapi_urls = vec![
Url::new("v2", concat!(api_base_2!(), "/openapi.json")),
Url::new("v3", concat!(api_base_3!(), "/openapi.json")),
];
let is_alive: Arc<AtomicBool> = Arc::new(AtomicBool::new(true));
loop {
let db_auth_tokens = config.auth.clone();
let pool = connect_postgres(config.database.clone()).await.unwrap();
let pool_copy = pool.clone();
let swagger_config = Config::new(openapi_urls.clone());
let mut openapi_v2 = ApiDocV2::openapi();
openapi_v2.info.title = "Chellaris Rust API".to_string();
let mut openapi_v3 = ApiDocV3::openapi();
openapi_v3.info.title = "Chellaris Rust API".to_string();
let server = HttpServer::new(move || {
App::new()
.app_data(web::Data::new(AppState { db: pool.clone(), auth_tokens: db_auth_tokens.clone() }))
.wrap(Logger::default())
// API v2 Endpoints
.service(v2::empire_ethics)
.service(v2::empires)
.service(v2::ethics)
.service(v2::game_groups)
.service(v2::games)
.service(v2::portrait_groups)
.service(v2::portraits)
// Swagger UI
.service(
SwaggerUi::new(concat!(api_base!(), "/swagger/{_:.*}"))
.urls(vec![
(
Url::new("v2", concat!(api_base_2!(), "/openapi.json")),
openapi_v2.clone(),
),
(
Url::new("v3", concat!(api_base_3!(), "/openapi.json")),
openapi_v3.clone(),
),
])
.config(swagger_config.clone()),
)
})
.bind((Ipv6Addr::UNSPECIFIED, 8080)).expect("Port or IP already occupied")
.run();
let server_thread = tokio::spawn(async {
eprintln!("Awaiting server");
let _ = server.await;
println!("Stopped awaiting server");
});
println!("Started Serving API on: ");
println!(" -> http://[{}]:{}", Ipv6Addr::UNSPECIFIED, 8080);
println!(" -> http://{}:{}", Ipv4Addr::UNSPECIFIED, 8080);
let is_alive_clone = Arc::clone(&is_alive);
let shutdown_clone = Arc::clone(&shutdown);
let _ = tokio::spawn(async move { postgres_watchdog(pool_copy, is_alive_clone, shutdown_clone).await });
//watchdog_thread.await;
while is_alive.load(Ordering::Relaxed) {
let thread = tokio::spawn(async {
thread::sleep(Duration::from_millis(100));
});
let _ = thread.await;
}
if shutdown.load(Ordering::Relaxed) {
break;
}
eprintln!("Connection died, restarting Server");
server_thread.abort();
}
Ok(())
}

260
src/v2/mod.rs Normal file
View file

@ -0,0 +1,260 @@
use actix_web::{web::{self, Json}, Responder, get};
use crate::{AppState, db};
pub(crate) mod schemas;
#[utoipa::path(
params(),
responses(
(status = 200, description = "OK", body = EmpireEthic),
),
security(
("api_key" = [])
),
)]
#[get("/empire_ethics")]
pub(crate) async fn empire_ethics(
data: web::Data<AppState>
) -> impl Responder {
let db_data: Vec<db::schemas::EmpireEthic> = sqlx::query_as(
"SELECT * FROM public.empire_ethics ORDER BY empires_id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::EmpireEthic> = vec![];
db_data.iter().for_each(|entry| {
let new_data = schemas::EmpireEthic {
empires_id: entry.empires_id,
empires_group_game_id: entry.empires_group_game_id,
empires_group_id: entry.empires_group_id,
ethics_id: entry.ethics_id,
ethics_fanatic: entry.ethics_fanatic
};
parsed_data.push(new_data);
});
Json(parsed_data)
}
#[utoipa::path(
params(
schemas::AuthParams
),
responses(
(status = 200, description = "OK", body = Empire),
),
security(
("api_key" = [])
),
)]
#[get("/empires")]
pub(crate) async fn empires(
data: web::Data<AppState>,
params: web::Query<schemas::AuthParams>
) -> impl Responder {
let params: schemas::AuthParams = params.into_inner();
let db_data: Vec<db::schemas::Empire> = sqlx::query_as(
"SELECT * FROM public.empires ORDER BY id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::Empire> = vec![];
db_data.iter().for_each(|entry| {
let mut new_data = schemas::Empire {
id: entry.id,
group_id: entry.group_id,
empire_portrait_group_id: entry.empire_portrait_group_id,
empire_portrait_id: entry.empire_portrait_id,
group_game_id: entry.group_game_id,
discord_user: None,
gestalt: entry.gestalt
};
if let Some(auth_token) = params.token.clone() {
if auth_token == data.auth_tokens.admin || auth_token == data.auth_tokens.moderator {
new_data.discord_user = entry.discord_user.clone();
}
}
parsed_data.push(new_data);
});
Json(parsed_data)
}
#[utoipa::path(
params(),
responses(
(status = 200, description = "OK", body = Ethic),
),
security(
("api_key" = [])
),
)]
#[get("/ethics")]
pub(crate) async fn ethics(
data: web::Data<AppState>
) -> impl Responder {
let db_data: Vec<db::schemas::Ethic> = sqlx::query_as(
"SELECT * FROM public.ethics ORDER BY id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::Ethic> = vec![];
db_data.iter().for_each(|entry| {
let new_data = schemas::Ethic {
id: entry.id,
machine_ethic: entry.machine_ethic,
name: entry.name.clone()
};
parsed_data.push(new_data);
});
Json(parsed_data)
}
#[utoipa::path(
params(),
responses(
(status = 200, description = "OK", body = GameGroup),
),
security(
("api_key" = [])
),
)]
#[get("/game_groups")]
pub(crate) async fn game_groups(
data: web::Data<AppState>
) -> impl Responder {
let db_data: Vec<db::schemas::GameGroup> = sqlx::query_as(
"SELECT * FROM public.game_groups ORDER BY id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::GameGroup> = vec![];
db_data.iter().for_each(|entry| {
let new_data = schemas::GameGroup {
game_id: entry.game_id,
id: entry.id,
name: entry.name.clone()
};
parsed_data.push(new_data);
});
Json(parsed_data)
}
#[utoipa::path(
params(),
responses(
(status = 200, description = "OK", body = Game),
),
security(
("api_key" = [])
),
)]
#[get("/games")]
pub(crate) async fn games(
data: web::Data<AppState>
) -> impl Responder {
let db_data: Vec<db::schemas::Game> = sqlx::query_as(
"SELECT * FROM public.games ORDER BY id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::Game> = vec![];
db_data.iter().for_each(|entry| {
let new_data = schemas::Game {
id: entry.id,
name: entry.name.clone()
};
parsed_data.push(new_data);
});
Json(parsed_data)
}
#[utoipa::path(
params(),
responses(
(status = 200, description = "OK", body = PortraitGroup),
),
security(
("api_key" = [])
),
)]
#[get("/portrait_groups")]
pub(crate) async fn portrait_groups(
data: web::Data<AppState>
) -> impl Responder {
let db_data: Vec<db::schemas::PortraitGroup> = sqlx::query_as(
"SELECT * FROM public.portrait_groups ORDER BY id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::PortraitGroup> = vec![];
db_data.iter().for_each(|entry| {
let new_data = schemas::PortraitGroup {
id: entry.id,
name: entry.name.clone()
};
parsed_data.push(new_data);
});
Json(parsed_data)
}
#[utoipa::path(
params(),
responses(
(status = 200, description = "OK", body = Portrait),
),
security(
("api_key" = [])
),
)]
#[get("/portraits")]
pub(crate) async fn portraits(
data: web::Data<AppState>
) -> impl Responder {
let db_data: Vec<db::schemas::Portrait> = sqlx::query_as(
"SELECT * FROM public.portraits ORDER BY id",
)
.fetch_all(&data.db)
.await.expect("Error Fetching Data from DB");
let mut parsed_data: Vec<schemas::Portrait> = vec![];
db_data.iter().for_each(|entry| {
let new_data = schemas::Portrait {
id: entry.id,
group_id: entry.group_id,
hires: entry.hires.clone(),
lores: entry.lores.clone()
};
parsed_data.push(new_data);
});
Json(parsed_data)
}

62
src/v2/schemas.rs Normal file
View file

@ -0,0 +1,62 @@
use serde::{Serialize, Deserialize};
use sqlx::FromRow;
use utoipa::{ToSchema, IntoParams};
#[derive(Serialize, Deserialize, ToSchema, Debug, FromRow, IntoParams)]
pub struct AuthParams {
pub token: Option<String>,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct PortraitGroup {
pub id: i32,
pub name: String,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Portrait {
pub id: i32,
pub group_id: i32,
pub hires: String,
pub lores: Option<String>,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Game {
pub id: i32,
pub name: String,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct GameGroup {
pub id: i32,
pub game_id: i32,
pub name: String,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Ethic {
pub id: i32,
pub name: String,
pub machine_ethic: bool,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct Empire {
pub id: i32,
pub discord_user: Option<String>,
pub group_id: i32,
pub gestalt: Option<bool>, // TODO: make nn in DB schema
pub empire_portrait_id: i32,
pub empire_portrait_group_id: i32,
pub group_game_id: i32,
}
#[derive(Serialize, ToSchema, Debug, FromRow)]
pub struct EmpireEthic {
pub empires_id: i32,
pub empires_group_id: i32,
pub empires_group_game_id: i32,
pub ethics_id: i32,
pub ethics_fanatic: bool,
}

314
yarn.lock Normal file
View file

@ -0,0 +1,314 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
ajv@^6.1.1:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
async@^2.0.1:
version "2.6.4"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
dependencies:
lodash "^4.17.14"
bignumber.js@9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075"
integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==
bson@~1.0.4:
version "1.0.9"
resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.9.tgz#12319f8323b1254739b7c6bef8d3e89ae05a2f57"
integrity sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==
buffer-shims@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
integrity sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g==
core-util-is@~1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
debug@*:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
double-ended-queue@^2.1.0-0:
version "2.1.0-0"
resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
integrity sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ==
es6-promise@3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
integrity sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g==
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
inherits@~2.0.1, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
lodash@^4.17.14, lodash@^4.17.4:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
mongo-sql@^2.7.5:
version "2.7.8"
resolved "https://registry.yarnpkg.com/mongo-sql/-/mongo-sql-2.7.8.tgz#f50184aaadc1be530db69e301ba35b01afd402d9"
integrity sha512-fJ4Tsn/G5QimXPRyoT0tnDhYdrPa/UJZY6FCJ4e9CYZgYH84w1qQrlednrpqgD9qK0oXtrLv78j1V+I5Yt/a6A==
mongodb-core@2.1.20:
version "2.1.20"
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.20.tgz#fece8dd76b59ee7d7f2d313b65322c160492d8f1"
integrity sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==
dependencies:
bson "~1.0.4"
require_optional "~1.0.0"
mongodb@^2.1.18:
version "2.2.36"
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.36.tgz#1c573680b2849fb0f47acbba3dc5fa228de975f5"
integrity sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==
dependencies:
es6-promise "3.2.1"
mongodb-core "2.1.20"
readable-stream "2.2.7"
monk-middleware-cast-ids@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/monk-middleware-cast-ids/-/monk-middleware-cast-ids-0.2.1.tgz#40c40e5a6cb33ccedc289220943275ee8861c529"
integrity sha512-Hp9gwjXo+inSPhXUlsV1u3DyZh2cXT3Osij/1gSNCJQCgacAF1lfmnTj6bKmlf1Et4dvLhwUL0PquxdZRIofkA==
monk-middleware-fields@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/monk-middleware-fields/-/monk-middleware-fields-0.2.0.tgz#ff637af35f5948879ccb2be15a91360911bea6c1"
integrity sha512-pp+k0JeBX+HkIKnCisrtsW/QM2WGkOVG1Bd1qKLSanuBCf1l5khpdHrEullfko0HO6tCjCJMp//MsR16gd5tAw==
monk-middleware-handle-callback@^0.2.0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/monk-middleware-handle-callback/-/monk-middleware-handle-callback-0.2.2.tgz#47de6cc1248726c72a2be0c81bc4e68310c32146"
integrity sha512-5hBynb7asZ2uw9XVze7C3XH0zXT51yFDvYydk/5HnWWzh2NLglDSiKDcX0yLKPHzFgiq+5Z4Laq5fFVnFsmm8w==
monk-middleware-options@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/monk-middleware-options/-/monk-middleware-options-0.2.1.tgz#58dae1c518d46636ebdff506fadfc773bb442886"
integrity sha512-ypE0wGC8n5ARvOq2tlERr1uyu1edckeDRkheQLaXPRm9LoW7kr9P7xMGEjW2vmBh7IxnkpONVc7555X8x+34hQ==
monk-middleware-query@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/monk-middleware-query/-/monk-middleware-query-0.2.0.tgz#a926c677d4a5620c62151b0a56d0c0c151675874"
integrity sha512-BApd5HBiczJl1eVy65c9/NBVLtygBePFxuoHgar/LeMWCjWP9odSJk3vsnbxTnsOT1CMJ+hFysbaosLzDsxvtA==
monk-middleware-wait-for-connection@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/monk-middleware-wait-for-connection/-/monk-middleware-wait-for-connection-0.2.0.tgz#312958d30e588b57d09754dd7c97b4843316835a"
integrity sha512-jSTz73B/+pGTTvhu5Ym8xsG6+QqaWab53UXnXdNNlTijTdLvcHABCLJXudQiJxob5N1Mzr5EOSx5ziwn2sihPQ==
monk@^6.0.5:
version "6.0.6"
resolved "https://registry.yarnpkg.com/monk/-/monk-6.0.6.tgz#2ff1cd57f001bba0fea73d1eea3952a7d35450c5"
integrity sha512-bSuADQGwIxBcRzCzQaMoGmiGl30Dr+0iB1FQAQb3VwWwAKbtpDN2wkVHCjthzw/jXhPHWxTQFUtlSt/nSagojQ==
dependencies:
debug "*"
mongodb "^2.1.18"
monk-middleware-cast-ids "^0.2.1"
monk-middleware-fields "^0.2.0"
monk-middleware-handle-callback "^0.2.0"
monk-middleware-options "^0.2.1"
monk-middleware-query "^0.2.0"
monk-middleware-wait-for-connection "^0.2.0"
object-assign "^4.1.1"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
mysql@^2.11.1:
version "2.18.1"
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717"
integrity sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==
dependencies:
bignumber.js "9.0.0"
readable-stream "2.3.7"
safe-buffer "5.1.2"
sqlstring "2.3.1"
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
integrity sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
punycode@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
readable-stream@2.2.7:
version "2.2.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1"
integrity sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==
dependencies:
buffer-shims "~1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
string_decoder "~1.0.0"
util-deprecate "~1.0.1"
readable-stream@2.3.7:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
redis-commands@^1.2.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==
redis-parser@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b"
integrity sha512-9Hdw19gwXFBJdN8ENUoNVJFRyMDFrE/ZBClPicKYDPwNPJ4ST1TedAHYNSiGKElwh2vrmRGMoJYbVdJd+WQXIw==
redis@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/redis/-/redis-2.8.0.tgz#202288e3f58c49f6079d97af7a10e1303ae14b02"
integrity sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==
dependencies:
double-ended-queue "^2.1.0-0"
redis-commands "^1.2.0"
redis-parser "^2.6.0"
require_optional@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
integrity sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==
dependencies:
resolve-from "^2.0.0"
semver "^5.1.0"
resolve-from@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
integrity sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
semver@^5.1.0:
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
sqlstring@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
integrity sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==
sqlx@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/sqlx/-/sqlx-4.3.2.tgz#e00e9c01543e776639b3622beee0b51f2e005b76"
integrity sha512-cKXn3T0fDhnX69F7556K0weGUYaBsmmtcIjTlj9OPQNxR56Lvil89pk5WntRR+h4IFFkrmKDg0yzl0YVsSDgbQ==
dependencies:
ajv "^6.1.1"
async "^2.0.1"
debug "^2.2.0"
lodash "^4.17.4"
mongo-sql "^2.7.5"
monk "^6.0.5"
mysql "^2.11.1"
redis "^2.8.0"
string_decoder@~1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==
dependencies:
safe-buffer "~5.1.0"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.0"
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==