UNPKG

appwrite-utils-cli

Version:

Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.

140 lines (139 loc) 5.26 kB
import { converterFunctions } from "appwrite-utils"; import { cloneDeep, isPlainObject } from "es-toolkit"; /** * Deeply converts all properties of an object (or array) to strings. * @param data The input data to convert. * @returns The data with all its properties converted to strings. */ export const deepAnyToString = (data) => { if (Array.isArray(data)) { return data.map((item) => deepAnyToString(item)); } else if (isPlainObject(data)) { return Object.keys(data).reduce((acc, key) => { acc[key] = deepAnyToString(data[key]); return acc; }, {}); } else { return converterFunctions.anyToString(data); } }; /** * Performs a deep conversion of all values in a nested structure to the specified type. * Uses a conversion function like anyToString, anyToNumber, etc. * @param data The data to convert. * @param convertFn The conversion function to apply. * @returns The converted data. */ export const deepConvert = (data, convertFn) => { if (Array.isArray(data)) { return data.map((item) => deepConvert(item, convertFn)); } else if (isPlainObject(data)) { return Object.keys(data).reduce((acc, key) => { acc[key] = deepConvert(data[key], convertFn); return acc; }, {}); } else { return convertFn(data); } }; /** * Converts an entire object's properties to different types based on a provided schema. * @param obj The object to convert. * @param schema A mapping of object keys to conversion functions. * @returns The converted object. */ export const convertObjectBySchema = (obj, schema) => { return Object.keys(obj).reduce((acc, key) => { const convertFn = schema[key]; acc[key] = convertFn ? convertFn(obj[key]) : obj[key]; return acc; }, {}); }; /** * Converts the keys of an object based on a provided attributeMappings. * Each key in the object is checked against attributeMappings; if a matching entry is found, * the key is renamed to the targetKey specified in attributeMappings. * * @param obj The object to convert. * @param attributeMappings The attributeMappings defining how keys in the object should be converted. * @returns The converted object with keys renamed according to attributeMappings. */ export const convertObjectByAttributeMappings = (obj, attributeMappings) => { const result = {}; // Correctly handle [any] notation by mapping or aggregating over all elements or keys const resolveValue = (obj, path) => { const parts = path.split("."); let current = obj; for (let i = 0; i < parts.length; i++) { if (parts[i] === "[any]") { if (Array.isArray(current)) { // If current is an array, apply resolution to each item return current.map((item) => resolveValue(item, parts.slice(i + 1).join("."))); } else if (typeof current === "object" && current !== null) { // If current is an object, aggregate values from all keys return Object.values(current).map((value) => resolveValue(value, parts.slice(i + 1).join("."))); } } else { current = current[parts[i]]; if (current === undefined) return undefined; } } return current; }; for (const mapping of attributeMappings) { if (mapping.valueToSet !== undefined) { result[mapping.targetKey] = mapping.valueToSet; } else if (Array.isArray(mapping.oldKeys)) { // Collect and flatten values from multiple oldKeys const values = mapping.oldKeys .map((oldKey) => resolveValue(obj, oldKey)) .flat(Infinity); if (values.length > 0) { result[mapping.targetKey] = values.filter((value) => value !== undefined); } else { result[mapping.targetKey] = null; } } else if (mapping.oldKey) { // Resolve single oldKey const value = resolveValue(obj, mapping.oldKey); if (value !== undefined) { result[mapping.targetKey] = Array.isArray(value) ? value.flat(Infinity) : value; } else { result[mapping.targetKey] = value ? value : null; } } } return result; }; /** * Ensures data conversion without mutating the original input. * @param data The data to convert. * @param convertFn The conversion function to apply. * @returns The converted data. */ export const immutableConvert = (data, convertFn) => { const clonedData = cloneDeep(data); return convertFn(clonedData); }; /** * Validates a string against a regular expression and returns the string if valid, or null. * @param value The string to validate. * @param pattern The regex pattern to validate against. * @returns The original string if valid, otherwise null. */ export const validateString = (value, pattern) => { return pattern.test(value) ? value : null; };