feat(backend): add delete-file action node - #25
Conversation
71bbc01 to
d89c340
Compare
Adds a `delete` action type that issues a WebDAV DELETE against the current resource path — the natural terminal step for cleanup workflows (e.g. removing files older than N days). Mirrors move/copy's existing shape: FileClient gains a Delete method, webdavfile.Client implements it against the same DAV endpoint used by copyOrMove, and runAction's new "delete" case sets result.Output to the deleted path and resets currentPath to "" so any subsequent file-needing action fails with the same "no target file" error tag/comment/move/copy already produce. Note: oCIS's WebDAV DELETE typically moves the resource to the space's trash rather than hard-deleting it (platform behavior). Covered by a new executor test asserting Delete is called with the right path, result.Output is set, and a chained action after delete fails because currentPath is now empty. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Lukas Hirt <info@hirt.cz>
Registers a new "Delete File" entry under the Actions picker category (actionType: 'delete', icon: delete-bin). Like tag/comment, it's a no-config action — it operates implicitly on the current file, so it needs no destination/newName param the way move/copy/rename do. NodeDetailsPanel already renders a no-config action correctly with no extra changes needed: none of its actionType branches match 'delete', so only the generic "Run only if" condition field shows. Adds Vitest coverage: nodeTypes.spec.ts asserts the action-delete entry exists under ACTION_CATEGORY and is discoverable via findNodeTypeForNode; NodeDetailsPanel.spec.ts and ActionNode.spec.ts add the first component-mount tests in this package, asserting the delete action renders its label/icon with zero action-specific fields (contrasted against tag's one field and move's destination field). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Lukas Hirt <info@hirt.cz>
d89c340 to
9eaa660
Compare
dj4oC
left a comment
There was a problem hiding this comment.
Review: feat(backend): add delete-file action node
Stats: +206/-2 across 8 files (backend + frontend)
Overview
Adds a delete action: issues a WebDAV DELETE against currentPath, sets result.Output to the deleted path, and — correctly — resets currentPath to "" afterward, so any later file-needing action in the same chain fails with the existing "no target file" error rather than silently operating on a stale/deleted path. This is the cleanest of the recent action-node PRs I've looked at in this repo: small, honest about platform behavior, and its test directly proves the currentPath-reset consequence rather than just asserting the happy path.
Code quality & style
webdavfile.Client.DeletemirrorscopyOrMove's structure closely (resolve user → build request → set auth header → check status), which keeps the file internally consistent rather than introducing a new shape for HTTP calls.- The doc comment on
Delete— "this typically moves the resource to the space's trash rather than hard-deleting it — platform behavior, not something this method implements or relies on" — is a responsible, appropriately hedged claim about behavior this code doesn't control. Good instinct not to overclaim data-safety guarantees it can't actually make. runAction's newcase "delete"correctly orders thecurrentPath == ""guard before callingDelete, matching the validation-then-act pattern every other file action already uses.
Minor observations (non-blocking)
- Consistency gap with the
vars-based output convention: like the currently-opencreateFolderPR (#24), this action setsresult.Outputbut never writes avars["delete.output"]entry, so a later node couldn't reference{{delete.output}}(e.g., anotifyaction saying "Deleted {{delete.output}}") even though that'd be a reasonable thing to want. Unlike #24, this PR's description doesn't claim that capability exists, so it's not a broken promise — just worth folding in if/when thevars["<actionType>.output"]convention from PR #23 gets applied consistently across the newer action types. - PR-description accuracy: the claim that
NodeDetailsPanel.spec.tsis among the "first component-mount tests in this package" doesn't hold — that file already hadmount()-based tests using a realcreateGettext()plugin prior to this PR (it's a modified file, not a new one, per the diff).ActionNode.spec.tsgenuinely is new, so the claim is accurate for that file specifically. I flagged this same over-claim pattern on PR #23's description — might be worth double-checking this boilerplate phrase before it goes into future PR descriptions from this branch of work. - Shared-file churn (FYI, not blocking): this PR, #24 (
createFolder), and others all insert their newNODE_TYPESentry at the same spot (immediately beforeaction-notify) and extend the sameActionTypeunion line intypes/workflow.ts. Not a defect in this PR, just a heads-up that whichever of these merges later will need a small, mechanical conflict resolution.
Test coverage
Good. TestRunDeleteAction is the standout — it doesn't just assert the delete call happened, it chains a tag action afterward and asserts it fails specifically because currentPath is now empty, which is exactly the behavior worth locking in given how easy it'd be to regress (e.g., accidentally not clearing currentPath, or clearing it but not surfacing a clear error downstream). Frontend coverage across nodeTypes.spec.ts, NodeDetailsPanel.spec.ts, and the new ActionNode.spec.ts appropriately proves the "zero config fields" claim by contrast against tag (one field) and move (destination field), rather than just asserting delete's own shape in isolation.
Security
The soft-delete-to-trash caveat is the right thing to flag rather than silently rely on. One open question worth a quick platform-level confirmation rather than a code change: does this hold for every oCIS space type (e.g., are there project-space or admin configurations where WebDAV DELETE is a hard delete)? If trash-recoverability isn't universal, this is the one action in the current palette where that distinction actually matters to an end user relying on it, and might be worth a one-line UI caveat rather than only a backend code comment.
Summary
Well-scoped, honestly documented, and the test suite specifically targets the behavior most likely to regress. Nothing here blocks merge.
🤖 Generated with Claude Code
Summary
Adds a new "Delete File" action node, end to end. Move/copy/rename already exist as file-operation actions; delete was the one basic operation conspicuously missing — the natural terminal step for cleanup workflows like "if a temp file is older than N days, delete it."
deleteaction type issues a WebDAVDELETEagainst the current resource path.webdavfile.Client.Delete(mirrorscopyOrMove's auth-header handling, minus theDestinationheader).FileClientinterface inexecutor.gogainsDelete.runAction's newcase "delete"setsresult.Outputto the deleted path and resetscurrentPathto"", so any later file-needing action in the same chain fails with the existing "no target file" error shape (same patterntag/comment/move/copyalready use).DELETEtypically moves the resource to the space's trash rather than hard-deleting it — platform behavior, not something this action implements or overclaims.action-deleteentry inNODE_TYPESunderACTION_CATEGORY(icondelete-bin),'delete'added to theActionTypeunion. It's a no-config action liketag/comment(no destination/newName param) —NodeDetailsPanel.vueneeded no changes since none of itsactionTypebranches matchdelete, so only the generic "Run only if" condition field renders.Test plan
TestRunDeleteActioninbackend/pkg/executor/executor_test.go— assertsDeleteis called with the correct path,result.Outputis the deleted path, and a chainedtagaction afterdeletefails becausecurrentPathis now empty. Written first, confirmed it failed for the right reason (missingDeletecall), then implemented.cd backend && go build ./... && go vet ./... && go test ./...— all pass.tests/unit/nodeTypes.spec.ts(new) — assertsaction-deleteexists underACTION_CATEGORYand is discoverable viafindNodeTypeForNode.tests/unit/NodeDetailsPanel.spec.tsandtests/unit/ActionNode.spec.ts(new, first component-mount tests in this package) — assert the delete action renders its label/icon with zero action-specific fields, contrasted againsttag(one field) andmove(destination field).cd frontend && npm run test:unit— 5 files / 11 tests pass.cd frontend && npm run check:types— clean.cd frontend && npm run lint— clean.🤖 Generated with Claude Code