forked from 1b-agent/opencadstudio-upstream
fix(blocks): one block definition service for delete, rename and purge on every path
new src/scene/block_service.rs (references, delete, rename, purge candidates, name validation, one error type and message). The command-line RENAME, palette Remove, plugin API, control/MCP block_delete and PURGE all use it. Layout, xref, dynamic-block, anonymous and open-in-editor records are protected; PURGE removes an anonymous block only when nothing references it. PROTOCOL CHANGE: control/MCP block_delete refuses a referenced block unless force=true (erases referencing INSERTs in one undo step). New REST route DELETE /api/v1/blocks/{name}?force=true. MCP tool digest re-pinned. Undo labels are Delete block X, Rename block X to Y and Purge.
This commit is contained in:
1 parent
5dfa41c032
commit
2b50b6c858
16 files changed
+2701
-262
No files matched your search
+24
-5
@@ -676,11 +676,22 @@ pub(crate) fn plan(method: &str, rest: &[&str], request: &HttpRequest) -> Plan {
|
||||
fields: body,
|
||||
created: 201,
|
||||
},
|
||||
("DELETE", ["blocks", name]) => Plan::Mutate {
|
||||
op: "block_delete".into(),
|
||||
fields: json!({"name": name}),
|
||||
created: 200,
|
||||
},
|
||||
("DELETE", ["blocks", name]) => {
|
||||
// `?force=true` mirrors the control op: it erases the referencing
|
||||
// inserts instead of refusing a referenced definition.
|
||||
let mut fields = json!({"name": name});
|
||||
if request
|
||||
.param("force")
|
||||
.is_some_and(|value| value == "true" || value == "1")
|
||||
{
|
||||
fields["force"] = json!(true);
|
||||
}
|
||||
Plan::Mutate {
|
||||
op: "block_delete".into(),
|
||||
fields,
|
||||
created: 200,
|
||||
}
|
||||
}
|
||||
("POST", ["file-identity"]) => Plan::Mutate {
|
||||
op: "file_identity".into(),
|
||||
fields: body,
|
||||
@@ -1440,13 +1451,21 @@ mod tests {
|
||||
&mut counter,
|
||||
);
|
||||
assert_eq!(status, 201, "{body}");
|
||||
// A definition the insert still points at is refused without force.
|
||||
let (status, body) = route(
|
||||
&mut app,
|
||||
&request("DELETE", "/api/v1/blocks/MARK", ""),
|
||||
&mut document_id,
|
||||
&mut counter,
|
||||
);
|
||||
assert_eq!(status, 400, "{body}");
|
||||
assert_eq!(body["code"], "block_referenced", "{body}");
|
||||
// `?force=true` erases the referencing insert in the same step.
|
||||
let mut forced = request("DELETE", "/api/v1/blocks/MARK", "");
|
||||
forced.query = vec![("force".into(), "true".into())];
|
||||
let (status, body) = route(&mut app, &forced, &mut document_id, &mut counter);
|
||||
assert_eq!(status, 200, "{body}");
|
||||
assert_eq!(body["result"]["references"], 1, "{body}");
|
||||
assert!(body["result"]["erased"].as_u64().unwrap() >= 1);
|
||||
let (status, body) = route(
|
||||
&mut app,
|
||||
|
||||
Reference in new issue
Block a user