Skip to content

Uploader: no public pre-upload hook to retarget the target entity (copy-on-write upload flows) #63

Description

@honzasladek

Missing API

Uploader offers no public way to intervene between "user dropped/selected files" and "the uploader starts writing into the target entity".

  • Uploader accepts no upload-event props — UploaderProps is only { entity, fileType, children } (src/components/Uploader.tsx:16), and the events passed to useFillEntity are hardcoded noops (src/components/Uploader.tsx:72).
  • useFillEntity closes over the entity accessor captured at mount when disconnecting/filling (src/internal/hooks/useFillEntity.ts:54), so the target cannot be swapped for an upload already in flight.

Use case (copy-on-write)

In a CMS media-library setup, a block references a shared ImageAsset (manyHasOne) whose image is the uploader target (<Uploader entity={block.imageAsset.image}>). When the referenced asset is already persisted (shared with other blocks), uploading a replacement file must NOT mutate the shared row in place — the block should first fork to a fresh asset and the upload should land there. Without a pre-upload hook there is no supported way to do this.

Current workaround (downstream)

We override UploaderUploadFilesContext between Uploader and UploaderDropzoneRoot: the wrapped dispatch queues the dropped File[], forks the relation ($disconnect() + $create(...)), remounts the Uploader via key={asset.$entity.id}, and an effect replays the queued files through the fresh uploader's raw useUploaderUploadFiles(). It works because UploaderDropzoneRoot takes its onDrop from that context (src/components/UploaderDropzoneRoot.tsx:13), but it leans on remount timing and on the context being a stable public seam.

Suggested API

Either of:

  • an async-capable onBeforeUpload(files: File[]) => File[] | false | Promise<...> prop on Uploader that runs before the entity write and after which the entity path is re-resolved, or
  • lazy per-upload resolution of the entity accessor (resolve the path at dispatch time instead of capturing at mount), which would make fork-then-upload work without remounting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions