import type { Field } from '@/types/field' /** Whether form values carry raw File references (multipart submit). */ export function formSubmissionValuesContainFiles(values: Record): boolean { for (const v of Object.values(values)) { if (v instanceof File) return true if (Array.isArray(v) && v.some((item) => item instanceof File)) return true } return false } function fileUploadMultipartSuffix(fieldKey: string, fileIndex: number): string { const base = fieldKey.replace(/[^a-zA-Z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'field' return fileIndex === 0 ? base : `${base}__${fileIndex}` } /** * multipart/form-data for form submission when file-upload fields carry File instances. */ export function buildMultipartFormSubmissionData(payload: { formId: string | number values: Record nonce: string postId: unknown referer: string formFields: Field[] }): FormData { const fd = new FormData() const valuesForJson: Record = { ...payload.values } const paramToLogicalKey: Record = {} for (const field of payload.formFields) { if (field.type !== 'file-upload') continue const key = `${field.type}_${field.fieldIndex}` const raw = valuesForJson[key] const files: File[] = [] if (raw instanceof File) files.push(raw) else if (Array.isArray(raw)) { for (const item of raw) { if (item instanceof File) files.push(item) } } delete valuesForJson[key] if (files.length === 0) continue files.forEach((file, idx) => { const suffix = fileUploadMultipartSuffix(key, idx) const param = `ivyforms_fu_${suffix}` fd.append(param, file) paramToLogicalKey[param] = key }) } fd.append('formId', String(payload.formId)) fd.append('nonce', String(payload.nonce)) fd.append('postId', String(payload.postId ?? '')) fd.append('referer', payload.referer ?? '') fd.append('values', JSON.stringify(valuesForJson)) fd.append('ivyforms_fm', JSON.stringify(paramToLogicalKey)) return fd }