fix local folder upload intent contract
This commit is contained in:
@@ -211,6 +211,7 @@ struct LocalAssetUploadFields {
|
||||
root_uri: String,
|
||||
document_id: String,
|
||||
target_relative_path: Option<String>,
|
||||
upload_intent: String,
|
||||
kind: String,
|
||||
}
|
||||
|
||||
@@ -3077,20 +3078,41 @@ pub async fn upload_local_markdown_asset(
|
||||
let fields = read_local_asset_upload_multipart(multipart).await?;
|
||||
ensure_local_workspace_write_access_with_state(&state, &context, &fields.root_uri)
|
||||
.map_err(|error| error.with_context(&context))?;
|
||||
let asset = if fields.target_relative_path.is_some() || fields.document_id.trim().is_empty() {
|
||||
write_local_folder_file_upload(
|
||||
&fields.root_uri,
|
||||
fields.target_relative_path.as_deref().unwrap_or(""),
|
||||
&fields.kind,
|
||||
fields.file,
|
||||
)?
|
||||
} else {
|
||||
write_local_markdown_asset(
|
||||
&fields.root_uri,
|
||||
&fields.document_id,
|
||||
&fields.kind,
|
||||
fields.file,
|
||||
)?
|
||||
let asset = match fields.upload_intent.as_str() {
|
||||
"editor.markdown.attach" => {
|
||||
if fields.document_id.trim().is_empty() || fields.target_relative_path.is_some() {
|
||||
return Err(WebError::bad_request_code(
|
||||
"local_asset_upload_intent_invalid",
|
||||
"editor.markdown.attach 必须提供 documentId 且不能提供 targetRelativePath",
|
||||
));
|
||||
}
|
||||
write_local_markdown_asset(
|
||||
&fields.root_uri,
|
||||
&fields.document_id,
|
||||
&fields.kind,
|
||||
fields.file,
|
||||
)?
|
||||
}
|
||||
"filetree.folder.drop" => {
|
||||
let Some(target_relative_path) = fields.target_relative_path.as_deref() else {
|
||||
return Err(WebError::bad_request_code(
|
||||
"local_asset_upload_intent_invalid",
|
||||
"filetree.folder.drop 必须提供 targetRelativePath",
|
||||
));
|
||||
};
|
||||
write_local_folder_file_upload(
|
||||
&fields.root_uri,
|
||||
target_relative_path,
|
||||
&fields.kind,
|
||||
fields.file,
|
||||
)?
|
||||
}
|
||||
_ => {
|
||||
return Err(WebError::bad_request_code(
|
||||
"local_asset_upload_intent_unsupported",
|
||||
"不支持的本地上传 intent",
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok((StatusCode::OK, Json(json!({ "ok": true, "asset": asset }))))
|
||||
}
|
||||
@@ -3361,6 +3383,7 @@ async fn read_local_asset_upload_multipart(
|
||||
let mut root_uri = String::new();
|
||||
let mut document_id = String::new();
|
||||
let mut target_relative_path: Option<String> = None;
|
||||
let mut upload_intent = String::new();
|
||||
let mut kind = String::new();
|
||||
|
||||
while let Some(field) = multipart.next_field().await.map_err(|error| {
|
||||
@@ -3413,6 +3436,7 @@ async fn read_local_asset_upload_multipart(
|
||||
"targetRelativePath" | "targetDirectoryPath" => {
|
||||
target_relative_path = Some(value.trim().to_string())
|
||||
}
|
||||
"uploadIntent" | "upload_intent" => upload_intent = value.trim().to_string(),
|
||||
"kind" => kind = value.trim().to_string(),
|
||||
_ => {}
|
||||
}
|
||||
@@ -3421,10 +3445,7 @@ async fn read_local_asset_upload_multipart(
|
||||
let file = file.ok_or_else(|| {
|
||||
WebError::bad_request_code("local_asset_upload_file_missing", "缺少 file")
|
||||
})?;
|
||||
if file.bytes.is_empty()
|
||||
|| root_uri.is_empty()
|
||||
|| (document_id.is_empty() && target_relative_path.is_none())
|
||||
{
|
||||
if file.bytes.is_empty() || root_uri.is_empty() || upload_intent.is_empty() {
|
||||
return Err(WebError::bad_request_code(
|
||||
"local_asset_upload_required_missing",
|
||||
"缺少必要参数",
|
||||
@@ -3435,6 +3456,7 @@ async fn read_local_asset_upload_multipart(
|
||||
root_uri,
|
||||
document_id,
|
||||
target_relative_path,
|
||||
upload_intent,
|
||||
kind,
|
||||
})
|
||||
}
|
||||
@@ -3501,6 +3523,7 @@ pub(crate) fn write_local_folder_file_upload(
|
||||
let asset_type = local_upload_asset_type(kind, &file.content_type);
|
||||
Ok(json!({
|
||||
"id": format!("local-file:{root_relative_path}"),
|
||||
"uploadIntent": "filetree.folder.drop",
|
||||
"asset_type": asset_type,
|
||||
"file_name": target.file_name().and_then(|value| value.to_str()).unwrap_or(&sanitized_name),
|
||||
"mime_type": file.content_type,
|
||||
@@ -3510,6 +3533,9 @@ pub(crate) fn write_local_folder_file_upload(
|
||||
"sourceKind": "local_folder",
|
||||
"rootUri": file_uri_for_path(&canonical_root),
|
||||
"rootRelativePath": root_relative_path,
|
||||
"targetRelativePath": target_relative_path,
|
||||
"markdownRelativePath": Value::Null,
|
||||
"ownerDocumentId": Value::Null,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -3610,6 +3636,7 @@ pub(crate) fn write_local_markdown_asset(
|
||||
write_uploaded_asset_index_metadata(&canonical_root, &uploaded_assets)?;
|
||||
Ok(json!({
|
||||
"id": format!("local:asset:{root_relative_path}"),
|
||||
"uploadIntent": "editor.markdown.attach",
|
||||
"asset_type": asset_type,
|
||||
"file_name": target.file_name().and_then(|value| value.to_str()).unwrap_or(&sanitized_name),
|
||||
"mime_type": file.content_type,
|
||||
@@ -3618,9 +3645,11 @@ pub(crate) fn write_local_markdown_asset(
|
||||
"sourcePath": markdown_relative_path,
|
||||
"document_id": document_id,
|
||||
"documentId": document_id,
|
||||
"ownerDocumentId": document_id,
|
||||
"sourceKind": "local_folder",
|
||||
"rootUri": file_uri_for_path(&canonical_root),
|
||||
"rootRelativePath": root_relative_path,
|
||||
"markdownRelativePath": markdown_relative_path,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -11509,6 +11538,13 @@ fn main() {}
|
||||
assert_eq!(asset["file_url"], "photo-1.png");
|
||||
assert_eq!(asset["asset_type"], "image");
|
||||
assert_eq!(asset["sourceKind"], "local_folder");
|
||||
assert_eq!(asset["uploadIntent"], "editor.markdown.attach");
|
||||
assert_eq!(asset["rootRelativePath"], "docs/README/photo-1.png");
|
||||
assert_eq!(asset["markdownRelativePath"], "photo-1.png");
|
||||
assert_eq!(
|
||||
asset["ownerDocumentId"],
|
||||
"local-md:docs~2FREADME~2FREADME.md"
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(root.join("docs").join("README").join("photo-1.png"))
|
||||
.expect("read copied asset"),
|
||||
@@ -11526,6 +11562,13 @@ fn main() {}
|
||||
)
|
||||
.expect("upload markdown asset");
|
||||
assert_eq!(markdown_asset["sourcePath"], "notes.md");
|
||||
assert_eq!(markdown_asset["uploadIntent"], "editor.markdown.attach");
|
||||
assert_eq!(markdown_asset["rootRelativePath"], "docs/README/notes.md");
|
||||
assert_eq!(markdown_asset["markdownRelativePath"], "notes.md");
|
||||
assert_eq!(
|
||||
markdown_asset["ownerDocumentId"],
|
||||
"local-md:docs~2FREADME~2FREADME.md"
|
||||
);
|
||||
let uploaded_asset_index =
|
||||
std::fs::read_to_string(root.join(".mnote").join("uploaded-assets.json"))
|
||||
.expect("uploaded asset index");
|
||||
|
||||
Reference in New Issue
Block a user