Added file upload support

This commit is contained in:
2026-06-04 04:20:05 -04:00
parent 4effcc7597
commit 67ad91b673
23 changed files with 665 additions and 20 deletions

View File

@@ -386,6 +386,18 @@ async function resolveHeaders(): Promise<Record<string, string>> {
}
}
/** Browser-safe `File` check — `File` is undefined under Node/SSR. */
function isFile(value: unknown): boolean {
return typeof File !== 'undefined' && value instanceof File
}
/** True when any arg is a file (or an array containing a file). */
function hasFileArg(args: Record<string, any>): boolean {
return Object.values(args).some(
(v) => isFile(v) || (Array.isArray(v) && v.some(isFile)),
)
}
/**
* Default Mizan transport — POST `${baseUrl}/call/` and GET
* `${baseUrl}/ctx/${name}/`. Compatible with `mizan-fastapi`,
@@ -397,13 +409,38 @@ export function httpTransport(): MizanTransport {
return {
async call(functionName, args) {
const headers = await resolveHeaders()
headers['Content-Type'] = 'application/json'
// File-typed args switch the call to multipart/form-data: `fn` and a
// JSON `args` part for the non-file fields, plus one part per file
// (an array field repeats its part). Otherwise JSON as usual. The
// server reconstructs the args dict by merging the file parts back in.
let body: BodyInit
if (hasFileArg(args)) {
const form = new FormData()
form.append('fn', functionName)
const jsonArgs: Record<string, any> = {}
for (const [key, value] of Object.entries(args)) {
if (isFile(value)) {
form.append(key, value)
} else if (Array.isArray(value) && value.some(isFile)) {
for (const item of value) form.append(key, item as Blob)
} else {
jsonArgs[key] = value
}
}
form.append('args', JSON.stringify(jsonArgs))
body = form
// Content-Type is set by the browser (with the multipart boundary).
} else {
headers['Content-Type'] = 'application/json'
body = JSON.stringify({ fn: functionName, args })
}
const res = await fetch(`${config.baseUrl}/call/`, {
method: 'POST',
headers,
credentials: 'same-origin',
body: JSON.stringify({ fn: functionName, args }),
body,
})
if (!res.ok) throw new MizanError(res.status, await res.text())
return res.json()