feat(openapi): complete upload preview and UI evidence
This commit is contained in:
+109
-4
@@ -11,6 +11,7 @@ use serde_json::{Value, json};
|
||||
use thiserror::Error;
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::dto::OpenApiUploadLocale;
|
||||
use crate::storage::StorageError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -96,6 +97,112 @@ impl ApiError {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn openapi_upload(locale: OpenApiUploadLocale, code: &'static str) -> Self {
|
||||
let russian = locale == OpenApiUploadLocale::Ru;
|
||||
let message = match (russian, code) {
|
||||
(_, "file_too_large") => {
|
||||
if russian {
|
||||
"файл OpenAPI превышает лимит 256 КиБ"
|
||||
} else {
|
||||
"OpenAPI file exceeds the 256 KiB limit"
|
||||
}
|
||||
}
|
||||
(_, "empty_file") => {
|
||||
if russian {
|
||||
"файл OpenAPI не должен быть пустым"
|
||||
} else {
|
||||
"OpenAPI file must not be empty"
|
||||
}
|
||||
}
|
||||
(_, "invalid_utf8") => {
|
||||
if russian {
|
||||
"файл OpenAPI должен быть в UTF-8"
|
||||
} else {
|
||||
"OpenAPI file must be UTF-8"
|
||||
}
|
||||
}
|
||||
(_, "invalid_media_type") => {
|
||||
if russian {
|
||||
"тип файла OpenAPI не поддерживается"
|
||||
} else {
|
||||
"OpenAPI file type is not supported"
|
||||
}
|
||||
}
|
||||
(_, "invalid_document") => {
|
||||
if russian {
|
||||
"некорректный или неподдерживаемый документ OpenAPI"
|
||||
} else {
|
||||
"OpenAPI document is invalid or unsupported"
|
||||
}
|
||||
}
|
||||
(_, "no_methods") => {
|
||||
if russian {
|
||||
"документ OpenAPI не содержит поддерживаемых методов"
|
||||
} else {
|
||||
"OpenAPI document contains no supported methods"
|
||||
}
|
||||
}
|
||||
(_, "source_integrity") => {
|
||||
if russian {
|
||||
"проверка целостности источника OpenAPI не пройдена"
|
||||
} else {
|
||||
"OpenAPI source integrity verification failed"
|
||||
}
|
||||
}
|
||||
(_, "source_unavailable") => {
|
||||
if russian {
|
||||
"источник OpenAPI недоступен"
|
||||
} else {
|
||||
"OpenAPI source is unavailable"
|
||||
}
|
||||
}
|
||||
(_, "parser_unavailable") | (_, "storage_unavailable") => {
|
||||
if russian {
|
||||
"обработка OpenAPI временно недоступна"
|
||||
} else {
|
||||
"OpenAPI processing is temporarily unavailable"
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if russian {
|
||||
"некорректная multipart-загрузка OpenAPI"
|
||||
} else {
|
||||
"invalid OpenAPI multipart upload"
|
||||
}
|
||||
}
|
||||
};
|
||||
let context = json!({ "error_code": format!("openapi_upload.{code}") });
|
||||
if code == "file_too_large" {
|
||||
Self::PayloadTooLarge {
|
||||
message: message.to_owned(),
|
||||
context: Some(context),
|
||||
}
|
||||
} else if matches!(code, "storage_unavailable" | "parser_unavailable") {
|
||||
Self::Internal {
|
||||
message: message.to_owned(),
|
||||
context: Some(context),
|
||||
}
|
||||
} else if matches!(code, "source_integrity" | "source_unavailable") {
|
||||
Self::Unprocessable {
|
||||
message: message.to_owned(),
|
||||
context: Some(context),
|
||||
}
|
||||
} else {
|
||||
Self::Validation {
|
||||
message: message.to_owned(),
|
||||
context: Some(context),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn source_unavailable() -> Self {
|
||||
Self::openapi_upload(OpenApiUploadLocale::En, "source_unavailable")
|
||||
}
|
||||
|
||||
pub(crate) fn source_integrity() -> Self {
|
||||
Self::openapi_upload(OpenApiUploadLocale::En, "source_integrity")
|
||||
}
|
||||
|
||||
pub(crate) fn rate_limited_with_context(message: impl Into<String>, context: Value) -> Self {
|
||||
Self::RateLimited {
|
||||
message: message.into(),
|
||||
@@ -588,17 +695,15 @@ impl From<RegistryError> for ApiError {
|
||||
format!("import job {job_id} was already applied with different parameters"),
|
||||
json!({ "job_id": job_id }),
|
||||
),
|
||||
RegistryError::SourceNotFound { source_id } => Self::not_found_with_context(
|
||||
RegistryError::SourceNotFound { .. } => Self::not_found_with_context(
|
||||
"artifact source was not found",
|
||||
json!({
|
||||
"source_id": source_id,
|
||||
"error_code": "artifact_source_not_found"
|
||||
}),
|
||||
),
|
||||
RegistryError::SourceConflict { source_id } => Self::conflict_with_context(
|
||||
RegistryError::SourceConflict { .. } => Self::conflict_with_context(
|
||||
"artifact source metadata or lifecycle conflicts with the request",
|
||||
json!({
|
||||
"source_id": source_id,
|
||||
"error_code": "artifact_source_conflict",
|
||||
"recovery": "reload"
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user