Skip to content

Commit

Permalink
OpenAPI Playground (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
harrysolovay authored Sep 26, 2024
1 parent 056a75c commit 8190607
Show file tree
Hide file tree
Showing 12 changed files with 337 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
DATABASE_URL=postgres://mina:whatever@localhost:5432/archive
RUST_LOG=debug,error,mina_mesh=info
RUST_ENV=production
65 changes: 65 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ cynic-querygen = "3.7.3"
indoc = "2.0.5"

[dependencies]
aide = { version = "0.13.4", features = ["scalar"] }
anyhow = "1.0.86"
axum = { version = "0.7.5", features = ["macros"] }
clap = { version = "4.5.11", features = ["derive", "env"] }
cynic = { version = "3.7.3", features = ["http-reqwest-blocking"] }
dotenv = "0.15.0"
envy = "0.4.2"
futures = "0.3.30"
mesh = { path = "./mesh_generated" }
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"mesh_generated/**",
"src/graphql/schema/mina_schema.graphql",
"sql/**",
"static/scalar.standalone.min.js",
"target/**"
],
"useGitignore": true
Expand Down
1 change: 1 addition & 0 deletions src/bin/mina_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum Command {

#[tokio::main]
async fn main() -> Result<()> {
dotenv::dotenv()?;
match Command::parse() {
Command::Serve(cmd) => cmd.run().await,
Command::FetchGenesisBlockIdentifier(cmd) => cmd.run().await,
Expand Down
14 changes: 11 additions & 3 deletions src/commands/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use clap::Args;
use paste::paste;
use tokio::net::TcpListener;

use crate::{util::Wrapper, MinaMesh, MinaMeshConfig};
use crate::{playground::handle_playground, util::Wrapper, MinaMesh, MinaMeshConfig};

#[derive(Debug, Args)]
#[command(about = "Start the Mina Mesh Server.")]
Expand All @@ -23,12 +23,17 @@ pub struct ServeCommand {
host: String,
#[arg(default_value = "3000")]
port: u16,
#[arg(env, long)]
playground: bool,
#[arg(env = "RUST_ENV", long)]
rust_env: String,
}

impl ServeCommand {
pub async fn run(self) -> Result<()> {
tracing_subscriber::fmt::init();
let mina_mesh = self.config.to_mina_mesh().await?;
let router = Router::new()
let mut router = Router::new()
.route("/account/balance", post(handle_account_balance))
.route("/block", post(handle_block))
.route("/call", post(handle_call))
Expand All @@ -47,8 +52,11 @@ impl ServeCommand {
.route("/network/options", post(handle_network_options))
.route("/network/status", post(handle_network_status))
.with_state(Arc::new(mina_mesh));
if self.rust_env == "development" || self.playground {
router = router.route("/", get(handle_playground));
}
let listener = TcpListener::bind(format!("{}:{}", self.host, self.port)).await?;
tracing::debug!("listening on {}", listener.local_addr()?);
tracing::info!("listening on http://{}", listener.local_addr()?);
serve(listener, router).await?;
Ok(())
}
Expand Down
20 changes: 10 additions & 10 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ use crate::{graphql::GraphQLClient, MinaMesh};

#[derive(Debug, Args)]
pub struct MinaMeshConfig {
#[arg(long, env, default_value_t = mina_proxy_url())]
pub mina_proxy_url: String,
#[arg(long, env, default_value_t = database_url())]
pub database_url: String,
#[arg(long, env, default_value_t = genesis_block_identifier_height())]
#[arg(long, env = "MINA_PROXY_URL", default_value_t = mina_proxy_url())]
pub proxy_url: String,
#[arg(long, env = "MINA_ARCHIVE_DATABASE_URL", default_value_t = database_url())]
pub archive_database_url: String,
#[arg(long, env = "MINA_GENESIS_BLOCK_IDENTIFIER_HEIGHT", default_value_t = genesis_block_identifier_height())]
pub genesis_block_identifier_height: i64,
#[arg(long, env, default_value_t = genesis_block_identifier_state_hash())]
#[arg(long, env = "MINA_GENESIS_BLOCK_IDENTIFIER_STATE_HASH", default_value_t = genesis_block_identifier_state_hash())]
pub genesis_block_identifier_state_hash: String,
}

impl MinaMeshConfig {
pub async fn to_mina_mesh(self) -> Result<MinaMesh> {
Ok(MinaMesh {
graphql_client: GraphQLClient::new(self.mina_proxy_url),
pg_pool: PgPool::connect(self.database_url.as_str()).await?,
graphql_client: GraphQLClient::new(self.proxy_url.to_owned()),
pg_pool: PgPool::connect(self.archive_database_url.as_str()).await?,
genesis_block_identifier: BlockIdentifier::new(
self.genesis_block_identifier_height,
self.genesis_block_identifier_state_hash.to_owned(),
Expand All @@ -33,8 +33,8 @@ impl MinaMeshConfig {
impl Default for MinaMeshConfig {
fn default() -> Self {
Self {
mina_proxy_url: mina_proxy_url(),
database_url: database_url(),
proxy_url: mina_proxy_url(),
archive_database_url: database_url(),
genesis_block_identifier_height: genesis_block_identifier_height(),
genesis_block_identifier_state_hash: genesis_block_identifier_state_hash(),
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod commands;
mod config;
mod error;
mod graphql;
mod playground;
mod util;

pub use api::*;
Expand Down
53 changes: 53 additions & 0 deletions src/playground.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use axum::{
debug_handler,
response::{Html, IntoResponse},
};

#[debug_handler]
pub async fn handle_playground() -> impl IntoResponse {
let html = format!(
r#"
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<title>{title}</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
<style>
body {{
margin: 0;
}}
</style>
</head>
<body>
<script
id="api-reference"></script>
<script>
var configuration = {{
theme: 'deepSpace',
customCss: `{scalar_css}`,
spec: {{
url: '{spec_url}'
}}
}}
var apiReference = document.getElementById('api-reference')
apiReference.dataset.configuration = JSON.stringify(configuration)
</script>
<script>{scalar_js}</script>
</body>
</html>
"#,
scalar_js = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/static/scalar.standalone.min.js")),
scalar_css = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/static/rust-theme.css")),
title = "MinaMesh Playground",
spec_url = OPENAPI_SPEC
);
Html(html)
}

static OPENAPI_SPEC: &str =
"https://raw.githubusercontent.com/coinbase/mesh-specifications/7f9f2f691f1ab1f7450e376d031e60d997dacbde/api.json";
Loading

0 comments on commit 8190607

Please sign in to comment.