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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions