fix openapi export duplicate issue and nits (#5971)
* nits and fix duplicate issue * update .sqlx * nits
This commit is contained in:
35
backend/.sqlx/query-33367c42e87e78ae987c0966dc4d445c5eff75b2e2843ffd7a46b03cbaea9ae8.json
generated
Normal file
35
backend/.sqlx/query-33367c42e87e78ae987c0966dc4d445c5eff75b2e2843ffd7a46b03cbaea9ae8.json
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT \n path,\n summary,\n description\n FROM\n flow\n WHERE\n path ~ ANY($1) AND\n workspace_id = $2 AND\n archived is FALSE\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "summary",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "description",
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"TextArray",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "33367c42e87e78ae987c0966dc4d445c5eff75b2e2843ffd7a46b03cbaea9ae8"
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55"
|
||||
|
||||
35
backend/.sqlx/query-dc36b46b9eb80cb7c92fa72519d117eda99a6f482a073ccd36a6431ef689a3fd.json
generated
Normal file
35
backend/.sqlx/query-dc36b46b9eb80cb7c92fa72519d117eda99a6f482a073ccd36a6431ef689a3fd.json
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT \n path,\n summary,\n description\n FROM\n script\n WHERE\n path ~ ANY($1) AND\n workspace_id = $2 AND\n archived is FALSE\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "summary",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "description",
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"TextArray",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "dc36b46b9eb80cb7c92fa72519d117eda99a6f482a073ccd36a6431ef689a3fd"
|
||||
}
|
||||
@@ -9,7 +9,6 @@ use axum::{
|
||||
};
|
||||
use http::{header, HeaderValue, Method, StatusCode};
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{to_value, Map, Value};
|
||||
use sqlx::PgConnection;
|
||||
@@ -24,9 +23,12 @@ use windmill_common::{
|
||||
use crate::db::ApiAuthed;
|
||||
|
||||
#[cfg(feature = "http_trigger")]
|
||||
use crate::{
|
||||
http_trigger_args::HttpMethod, http_trigger_auth::ApiKeyAuthentication,
|
||||
http_triggers::AuthenticationMethod, resources::try_get_resource_from_db_as,
|
||||
use {
|
||||
crate::{
|
||||
http_trigger_args::HttpMethod, http_trigger_auth::ApiKeyAuthentication,
|
||||
http_triggers::AuthenticationMethod, resources::try_get_resource_from_db_as,
|
||||
},
|
||||
itertools::Itertools,
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@@ -311,9 +313,15 @@ fn generate_paths(
|
||||
}
|
||||
};
|
||||
|
||||
let mut duplicate_webhooks = HashSet::new();
|
||||
let mut webhooks = HashSet::new();
|
||||
|
||||
for path in paths {
|
||||
if let Kind::Webhook(WebhookConfig { runnable_kind }) = &path.kind {
|
||||
if !webhooks.insert((path.route_path.clone(), runnable_kind.to_owned())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let (route_paths, parameters) =
|
||||
from_route_path_to_openapi_path(&path.route_path, &path.kind)?;
|
||||
|
||||
@@ -340,9 +348,6 @@ fn generate_paths(
|
||||
|
||||
let (methods, is_webhook) = match &path.kind {
|
||||
Kind::Webhook(_) => {
|
||||
if !duplicate_webhooks.insert(route_path.clone()) {
|
||||
return Err(anyhow!("Found duplicate webhook: {}", path.route_path).into());
|
||||
}
|
||||
is_async = route_path.starts_with("/run/");
|
||||
let methods = if is_async {
|
||||
vec![Method::POST]
|
||||
@@ -354,7 +359,12 @@ fn generate_paths(
|
||||
}
|
||||
Kind::HttpRoute(HttpRouteConfig { method }) => {
|
||||
if path_object.get(&method.to_string()).is_some() {
|
||||
return Err(anyhow!("Found duplicate route: {}", path.route_path).into());
|
||||
return Err(anyhow!(
|
||||
"Found duplicate {} method, for route at path: {}",
|
||||
method,
|
||||
path.route_path
|
||||
)
|
||||
.into());
|
||||
}
|
||||
is_async = path.is_async.unwrap_or(true);
|
||||
(vec![method.to_owned()], false)
|
||||
@@ -809,14 +819,6 @@ async fn webhook_to_future_paths(
|
||||
summary: Option<String>,
|
||||
}
|
||||
|
||||
impl PartialEq for MinifiedWebhook {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.path == other.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for MinifiedWebhook {}
|
||||
|
||||
let webhook_scripts = sqlx::query_as!(
|
||||
MinifiedWebhook,
|
||||
r#"SELECT
|
||||
@@ -827,16 +829,14 @@ async fn webhook_to_future_paths(
|
||||
script
|
||||
WHERE
|
||||
path ~ ANY($1) AND
|
||||
workspace_id = $2
|
||||
workspace_id = $2 AND
|
||||
archived is FALSE
|
||||
"#,
|
||||
&script_webhook_filter,
|
||||
&w_id
|
||||
)
|
||||
.fetch_all(&mut *pg_pool)
|
||||
.await?
|
||||
.into_iter()
|
||||
.unique()
|
||||
.collect_vec();
|
||||
.await?;
|
||||
|
||||
let webhook_flows = sqlx::query_as!(
|
||||
MinifiedWebhook,
|
||||
@@ -848,16 +848,14 @@ async fn webhook_to_future_paths(
|
||||
flow
|
||||
WHERE
|
||||
path ~ ANY($1) AND
|
||||
workspace_id = $2
|
||||
workspace_id = $2 AND
|
||||
archived is FALSE
|
||||
"#,
|
||||
&flow_webhook_filter,
|
||||
&w_id
|
||||
)
|
||||
.fetch_all(&mut *pg_pool)
|
||||
.await?
|
||||
.into_iter()
|
||||
.unique()
|
||||
.collect_vec();
|
||||
.await?;
|
||||
|
||||
openapi_future_paths.reserve_exact(webhook_scripts.len() + webhook_flows.len());
|
||||
|
||||
|
||||
@@ -47,11 +47,31 @@
|
||||
let licenseName = $state('')
|
||||
let licenseUrl = $state('')
|
||||
let isGeneratingOpenapiSpec = $state(false)
|
||||
let openapiDocument = $state('')
|
||||
let openapiDocument = $state(
|
||||
'# Click "Generate OpenAPI document" to generate your OpenAPI spec.'
|
||||
)
|
||||
let lang: OpenapiSpecFormat = $state('yaml')
|
||||
let editor: SimpleEditor | undefined = $state()
|
||||
let generateCurlCommandDrawer: Drawer | undefined = $state()
|
||||
let webhookAndHttpRouteFilter: HttpRouteAndWebhook[] = $state([])
|
||||
let webhookAndHttpRouteFilter: HttpRouteAndWebhook[] = $state([
|
||||
{
|
||||
user_or_folder_regex: '*',
|
||||
user_or_folder_regex_value: '*',
|
||||
path: '*',
|
||||
runnable_kind: 'script'
|
||||
},
|
||||
{
|
||||
user_or_folder_regex: '*',
|
||||
user_or_folder_regex_value: '*',
|
||||
path: '*',
|
||||
runnable_kind: 'flow'
|
||||
},
|
||||
{
|
||||
folder_regex: '*',
|
||||
path_regex: '*',
|
||||
route_path_regex: '*'
|
||||
}
|
||||
])
|
||||
let disabled = $derived(webhookAndHttpRouteFilter.length === 0)
|
||||
let token = $state('')
|
||||
let obj: Record<string, unknown> = $state({})
|
||||
@@ -556,8 +576,6 @@ curl -X POST "${window.location.origin}${base}/api/w/${$workspaceStore!}/openapi
|
||||
</div>
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
variant="border"
|
||||
spacingSize="sm"
|
||||
loading={isGeneratingOpenapiSpec}
|
||||
on:click={async () => {
|
||||
|
||||
Reference in New Issue
Block a user