remix-conform-rpc
Version:
Supercharge your remix/react-router actions and loaders with typesafe param and query parsing using conform and zod
66 lines • 2.03 kB
JavaScript
export function serializeToFormData(data) {
if (data instanceof FormData) {
return data;
}
const formData = new FormData();
if (isObject(data)) {
serializeData(data, [], formData);
}
return formData;
}
function serializeData(data, path, formData) {
if (isArray(data)) {
serializeArray(data, path, formData);
return;
}
if (isObject(data)) {
const entries = Object.entries(data);
for (const [key, value] of entries) {
const newPath = [...path, { type: "object", key, delimiter: shouldHaveDelimiter(value) }];
serializeData(value, newPath, formData);
}
return;
}
if (shouldAddData(data)) {
formData.append(constructPath(path), serializePrimitive(data));
}
}
function serializeArray(entries, path, formData) {
entries.forEach((value, index) => {
const newPath = [...path, { type: "array", index, delimiter: shouldHaveDelimiter(value) }];
serializeData(value, newPath, formData);
});
}
function isArray(value) {
return Array.isArray(value);
}
function isObject(value) {
return !isArray(value) && typeof value === "object" && value !== null;
}
function shouldAddData(data) {
return typeof data !== "function" && !!data;
}
/**
* Check if an object should have a delimiter (dot) in the path
*/
function shouldHaveDelimiter(childEntry) {
return isObject(childEntry) && Object.keys(childEntry).length >= 1;
}
function constructPath(elements) {
return elements.map((element) => {
if (element.type === "array") {
return `[${element.index}]${element.delimiter ? "." : ""}`;
}
return `${element.key}${element.delimiter ? "." : ""}`;
}).join("");
}
function serializePrimitive(value) {
if (value instanceof Date) {
return value.toISOString();
}
if (typeof value === "boolean") {
return value ? "on" : "";
}
return String(value);
}
//# sourceMappingURL=serialize-to-form-data.js.map