ak-zod-form-kit
Version:
A powerful utility library for processing, transforming, and validating form data with Zod.
161 lines (160 loc) • 6.26 kB
JavaScript
/**
* Convertit un objet JavaScript standard en un objet `FormData` pour l'envoi via des requêtes HTTP
* (par exemple, `fetch` ou `XMLHttpRequest`). Cette fonction gère intelligemment différents types de données,
* y compris les primitifs, les `File`s, les `Blob`s, les `Date`s, les tableaux et les objets imbriqués,
* en les sérialisant correctement pour le format `multipart/form-data`.
*
* @param {Record<string, unknown>} inputObject - L'objet JavaScript à convertir.
* @returns {FormData} L'objet `FormData` résultant, prêt pour l'envoi.
*
* @example
* const userData = {
* name: 'Alice',
* age: 28,
* preferences: {
* newsletter: true,
* themes: ['dark', 'light']
* },
* avatar: new File(['content'], 'avatar.png', { type: 'image/png' }),
* registrationDate: new Date(),
* emptyField: null
* };
* const formDataToSend = convertObjectToFormData(userData);
* // formDataToSend contiendra des entrées comme :
* // 'name': 'Alice'
* // 'age': '28'
* // 'preferences[newsletter]': 'true'
* // 'preferences[themes]': 'dark'
* // 'preferences[themes]': 'light'
* // 'avatar': (File object)
* // 'registrationDate': (ISO string de la date)
* // 'emptyField': ''
*/
// export function convertObjectToFormData(
// inputObject: Record<string, unknown>
// ): FormData {
// const sendFormData = new FormData();
// /**
// * Fonction récursive helper pour ajouter des paires clé-valeur au FormData.
// * Gère la sérialisation de types complexes.
// * @param {string} key - La clé du champ (peut inclure la notation crochets pour les imbrications).
// * @param {unknown} value - La valeur du champ à ajouter.
// */
// function appendDataRecursively(key: string, value: unknown) {
// // Cas null ou undefined : append comme chaîne vide
// if (value === null || value === undefined) {
// sendFormData.append(key, '');
// return;
// }
// // Cas File : append directement avec le nom
// if (value instanceof File) {
// sendFormData.append(key, value, value.name);
// return;
// }
// // Cas Blob : append directement
// if (value instanceof Blob) {
// sendFormData.append(key, value);
// return;
// }
// // Cas Date : convertit en chaîne ISO 8601
// if (value instanceof Date) {
// sendFormData.append(key, value.toISOString());
// return;
// }
// // Cas tableau : itère sur les éléments
// if (Array.isArray(value)) {
// value.forEach((item, index) => {
// // Pour les éléments complexes (tableaux ou objets) dans un tableau, récursivité avec index
// if (Array.isArray(item) || isPlainObject(item)) {
// appendDataRecursively(`${key}[${index}]`, item);
// } else {
// // Les éléments primitifs sont ajoutés avec la même clé pour gérer les listes de valeurs
// sendFormData.append(key, String(item));
// }
// });
// return;
// }
// // Cas objet simple (non-null, non-File/Blob/Date/Array) : récursivité pour chaque propriété
// if (isPlainObject(value)) {
// Object.entries(value).forEach(([propertyKey, propertyValue]) => {
// appendDataRecursively(`${key}[${propertyKey}]`, propertyValue);
// });
// return;
// }
// // Cas des types primitifs (string, number, boolean) : convertit en string
// sendFormData.append(key, String(value));
// }
// /**
// * Fonction utilitaire pour vérifier si une valeur est un objet simple (non null, non tableau, non instance de types spécifiques).
// * @param {unknown} value - La valeur à vérifier.
// * @returns {value is Record<string, unknown>} Vrai si la valeur est un objet JavaScript simple, Faux sinon.
// */
// function isPlainObject(value: unknown): value is Record<string, unknown> {
// return (
// typeof value === 'object' &&
// value !== null &&
// value.constructor === Object
// );
// }
// // Lance le processus d'ajout pour chaque entrée de l'objet initial
// Object.entries(inputObject).forEach(([key, value]) => {
// appendDataRecursively(key, value);
// });
// return sendFormData;
// }
export function convertObjectToFormData(formData) {
const sendFormData = new FormData();
function appendFormData(key, value) {
// Cas null ou undefined
if (value === null || value === undefined) {
sendFormData.append(key, '');
return;
}
// Cas File
if (value instanceof File) {
sendFormData.append(key, value, value.name);
return;
}
// Cas Blob
if (value instanceof Blob) {
sendFormData.append(key, value);
return;
}
// Cas Date
if (value instanceof Date) {
sendFormData.append(key, value.toISOString());
return;
}
// Cas tableau
if (Array.isArray(value)) {
value.forEach((item, index) => {
// Pour les tableaux imbriqués ou objets dans les tableaux
if (Array.isArray(item) || isObject(item)) {
appendFormData(key + '[' + index + ']', item);
}
else {
appendFormData(key, item);
}
});
return;
}
// Cas objet (excluant les types spéciaux déjà traités)
if (isObject(value)) {
Object.entries(value).forEach(([propertyKey, propertyValue]) => {
appendFormData(key + '[' + propertyKey + ']', propertyValue);
});
return;
}
// Cas des types primitifs (string, number, boolean)
sendFormData.append(key, String(value));
}
// Fonction utilitaire pour vérifier si une valeur est un objet
function isObject(value) {
return typeof value === 'object' && value !== null && !(value instanceof File) && !(value instanceof Blob) && !(value instanceof Date) && !Array.isArray(value);
}
// Traitement de chaque entrée du formData initial
Object.entries(formData).forEach(([key, value]) => {
appendFormData(key, value);
});
return sendFormData;
}