Browse API 1 documentation
grove.uploads.register()
Register an upload-provider implementation declared by the package.
Register an upload-provider implementation declared by the package.
Signature
grove.uploads.register(providerID: string, handler: (
file: GroveUploadFile, context: GroveUploadContext
) => string | { url: string } | Promise<string | { url: string }>): void
interface GroveUploadFile {
readonly name: string; readonly type: string; readonly size: number
read(offset: number, length: number): Promise<Uint8Array>
}
interface GroveUploadContext { progress(fraction: number): void }
Availability
Exclusive headless Root with uploads.provide and a matching contributions.uploadProviders entry. Application Roots are suitable for an app-wide service; server Roots can keep separate network accounts.
Parameters
| Parameter | Required | Description |
|---|---|---|
providerID |
Yes | Exact provider id from the manifest, not its globally namespaced preference ID. |
handler |
Yes | Function invoked for a native user-selected file. May return a value or Promise. |
file.name |
Host input | Filename only, no local path. Treat as untrusted. |
file.type |
Host input | Native MIME-type guess; not verified content. |
file.size |
Host input | Nonnegative byte count. Manifest maxFileSize is enforced before the handler runs. |
file.read |
Host input | Bounded read of this selected file; see its dedicated page. |
context.progress |
Host input | Report a progress fraction; see its dedicated page. |
Return value
Registration returns undefined. The handler must return a shareable HTTP/HTTPS URL string or { url: string }, optionally through a Promise. Return the recipient-facing URL, which may differ from an upload resource URL.
Behavior and errors
An empty provider id or non-function handler is a JavaScript no-op. Registering again replaces that handler. Native validation refuses undeclared IDs, non-headless surfaces, and missing grants. At most eight manifest providers are supported. File/context wrappers are frozen and valid only for the active upload.
Throw Error with a short user-safe explanation on failure. Mango bounds error text to 512 characters and presents the upload failure. Invalid returned URLs also fail the upload. Do not include credentials or private service responses in errors. The URL goes into the native draft for review; completing an upload does not send IRC traffic. Application Roots register in each mirrored runtime; do not assume one global singleton.
Example
grove.uploads.register('primary', async (file, context) => {
// This illustrative endpoint accepts one small raw file and returns { url }.
if (file.size === 0 || file.size > 1024 * 1024) {
throw new Error('This example accepts files up to 1 MiB.')
}
const bytes = await file.read(0, file.size)
const response = await fetch('https://uploads.example.com/files', {
method: 'POST', body: bytes, credentials: 'omit', redirect: 'error'
})
if (!response.ok) throw new Error('The upload service rejected the file.')
const result = await response.json()
const url = new URL(result.url)
if (url.protocol !== 'https:' || url.origin !== 'https://uploads.example.com') {
throw new Error('The upload service returned an invalid share URL.')
}
context.progress(1)
return { url: url.toString() }
})
See file.read(), context.progress(), and the complete Upload providers guide. Browser fetch in this example requires HTTPS host permission and service CORS; it is distinct from the native request bridge.