use std::collections::HashMap;
use std::path::Path;
use wick_asset_reference::AssetReference;
use wick_packet::RuntimeConfig;
use super::index_to_router_id;
use super::middleware::expand_for_middleware_components;
use crate::config::common::HttpMethod;
use crate::config::template_config::Renderable;
use crate::config::{self, Binding, ComponentOperationExpression, ImportDefinition};
use crate::error::ManifestError;
#[derive(
Debug,
Clone,
PartialEq,
derive_builder::Builder,
derive_asset_container::AssetManager,
property::Property,
serde::Serialize,
)]
#[asset(asset(AssetReference))]
#[property(get(public), set(private), mut(public, suffix = "_mut"))]
pub struct RestRouterConfig {
#[asset(skip)]
#[property(get(disable))]
pub(crate) path: String,
#[property(get(disable), mut(disable))]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) middleware: Option<super::middleware::Middleware>,
#[asset(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) tools: Option<Tools>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub(crate) routes: Vec<RestRoute>,
#[asset(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) info: Option<Info>,
}
impl Renderable for RestRouterConfig {
fn render_config(
&mut self,
source: Option<&Path>,
root_config: Option<&RuntimeConfig>,
env: Option<&HashMap<String, String>>,
) -> Result<(), ManifestError> {
self.middleware.render_config(source, root_config, env)?;
self.routes.render_config(source, root_config, env)
}
}
impl Renderable for RestRoute {
fn render_config(
&mut self,
source: Option<&Path>,
root_config: Option<&RuntimeConfig>,
env: Option<&HashMap<String, String>>,
) -> Result<(), ManifestError> {
self.operation.render_config(source, root_config, env)
}
}
impl super::WickRouter for RestRouterConfig {
fn middleware(&self) -> Option<&super::Middleware> {
self.middleware.as_ref()
}
fn middleware_mut(&mut self) -> Option<&mut super::Middleware> {
self.middleware.as_mut()
}
fn path(&self) -> &str {
&self.path
}
}
#[derive(Debug, Default, Clone, PartialEq, property::Property, serde::Serialize)]
#[property(get(public), set(disable), mut(disable))]
#[allow(missing_copy_implementations)]
pub struct Tools {
pub(crate) openapi: bool,
}
#[derive(Debug, Default, Clone, PartialEq, property::Property, serde::Serialize)]
#[property(get(public), set(private), mut(disable))]
pub struct Info {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) tos: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) contact: Option<Contact>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) license: Option<License>,
pub(crate) version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) documentation: Option<Documentation>,
}
#[derive(Debug, Default, Clone, PartialEq, property::Property, serde::Serialize)]
#[property(get(public), set(private), mut(disable))]
pub struct Documentation {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) description: Option<String>,
}
#[derive(Debug, Default, Clone, PartialEq, property::Property, serde::Serialize)]
#[property(get(public), set(private), mut(disable))]
pub struct License {
pub(crate) name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) url: Option<String>,
}
#[derive(Debug, Default, Clone, PartialEq, property::Property, serde::Serialize)]
#[property(get(public), set(private), mut(disable))]
pub struct Contact {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) email: Option<String>,
}
#[derive(
Debug,
Clone,
PartialEq,
derive_builder::Builder,
derive_asset_container::AssetManager,
property::Property,
serde::Serialize,
)]
#[asset(asset(AssetReference))]
#[property(get(public), set(private), mut(public, suffix = "_mut"))]
pub struct RestRoute {
#[asset(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) id: Option<String>,
#[asset(skip)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub(crate) methods: Vec<HttpMethod>,
#[asset(skip)]
pub(crate) sub_path: String,
pub(crate) operation: ComponentOperationExpression,
#[asset(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) description: Option<String>,
#[asset(skip)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) summary: Option<String>,
}
pub(crate) fn process_runtime_config(
trigger_index: usize,
index: usize,
router_config: &mut RestRouterConfig,
bindings: &mut Vec<Binding<ImportDefinition>>,
) -> Result<(), ManifestError> {
expand_for_middleware_components(trigger_index, index, router_config, bindings)?;
for (i, route) in router_config.routes_mut().iter_mut().enumerate() {
let component_id = format!("{}_{}", index_to_router_id(trigger_index, index), i);
route.operation_mut().maybe_import(&component_id, bindings);
}
let router_component = config::ComponentDefinition::Native(config::components::NativeComponent {});
let router_binding = config::Binding::new(
index_to_router_id(trigger_index, index),
ImportDefinition::component(router_component),
);
bindings.push(router_binding);
Ok(())
}