{"version":3,"file":"logic.mjs","names":[],"sources":["../src/logic.ts"],"sourcesContent":["import type { SchemaProvider } from \"./schema-provider\";\nimport type { ParsedField, ParsedSchema } from \"./types\";\n\nfunction assertSchemaProvider(\n  schemaProvider: unknown,\n): asserts schemaProvider is SchemaProvider {\n  if (!schemaProvider) {\n    throw new Error(\"AutoForm requires a schema prop. Provide a schema.\");\n  }\n\n  const provider = schemaProvider as Record<string, unknown>;\n  if (\n    typeof schemaProvider !== \"object\" ||\n    typeof provider?.parseSchema !== \"function\" ||\n    typeof provider?.validateSchema !== \"function\" ||\n    typeof provider?.getDefaultValues !== \"function\"\n  ) {\n    throw new Error(\n      \"AutoForm schema must be a schema provider. For Zod, const schemaProvider = new ZodProvider(schema);\",\n    );\n  }\n}\n\nexport function parseSchema(schemaProvider: SchemaProvider): ParsedSchema {\n  assertSchemaProvider(schemaProvider);\n  const schema = schemaProvider.parseSchema();\n  return {\n    ...schema,\n    fields: sortFieldsByOrder(schema.fields),\n  };\n}\n\nexport function validateSchema(schemaProvider: SchemaProvider, values: any) {\n  assertSchemaProvider(schemaProvider);\n  return schemaProvider.validateSchema(values);\n}\n\nexport function getDefaultValues(\n  schemaProvider: SchemaProvider,\n): Record<string, any> {\n  assertSchemaProvider(schemaProvider);\n  return schemaProvider.getDefaultValues();\n}\n\n/**\n * Recursively remove empty values from an object (null, undefined, '')\n * Used in AutoForm before calling the resolver to prevent empty values from being validated.\n * This is necessary because zod's optional() allows undefined, but form fields default to\n * empty strings even when untouched. These defaults makes the optional() unusable.\n * and cause validation issues in react-hook-form.\n */\n\nexport function removeEmptyValues<T extends Record<string, any>>(\n  values: T,\n): Partial<T> {\n  const result: Partial<T> = {};\n  for (const key in values) {\n    const value = values[key];\n    // includes method cannot check {}, []\n    if ([null, undefined, \"\", [], {}].includes(value)) {\n      continue;\n    }\n\n    if (Array.isArray(value)) {\n      const newArray = value.map((item: any) => {\n        if (typeof item === \"object\") {\n          return removeEmptyValues(item);\n        }\n        return item;\n      });\n      result[key] = newArray.filter((item: any) => item !== null);\n    } else if (typeof value === \"object\") {\n      result[key] = removeEmptyValues(value) as any;\n    } else {\n      result[key] = value;\n    }\n  }\n\n  return result;\n}\n\n/**\n * Recursively replaces empty values from an object (null, undefined, \"\", [], {}).\n * - Retains objects such as (Date, RegExp, functions, etc.) used in resolver.\n */\nconst isPlainObject = (value: any): boolean =>\n  typeof value === \"object\" &&\n  Object.prototype.toString.call(value) === \"[object Object]\";\n\nconst isEmpty = (value: any): boolean => [null, undefined, \"\"].includes(value); // includes method cannot check {}, []\n\nexport function replaceEmptyValue<T extends Record<string, any>>(values: T): T {\n  const result = { ...values };\n  for (const key in values) {\n    const value = values[key];\n\n    if (isEmpty(value)) {\n      (result[key] as any) = undefined;\n      continue;\n    }\n\n    if (Array.isArray(value)) {\n      const cleaned = Object.values(replaceEmptyValue({ ...value }));\n      result[key] = cleaned as any;\n    } else if (isPlainObject(value)) {\n      const cleaned = replaceEmptyValue(value);\n      result[key] = cleaned as any;\n    } else {\n      result[key] = value;\n    }\n  }\n\n  return result;\n}\n\n/**\n * Sort the fields by order.\n * If no order is set, the field will be sorted based on the order in the schema.\n */\nexport function sortFieldsByOrder(\n  fields: ParsedField[] | undefined,\n): ParsedField[] {\n  if (!fields) return [];\n  const sortedFields = fields\n    .map((field): ParsedField => {\n      if (field.schema) {\n        return {\n          ...field,\n          schema: sortFieldsByOrder(field.schema),\n        };\n      }\n      return field;\n    })\n    .sort((a, b) => {\n      const fieldA: number = a.fieldConfig?.order ?? 0;\n      const fieldB = b.fieldConfig?.order ?? 0;\n      return fieldA - fieldB;\n    });\n\n  return sortedFields;\n}\n"],"mappings":";AAGA,SAAS,qBACP,gBAC0C;CAC1C,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,oDAAoD;CAGtE,MAAM,WAAW;CACjB,IACE,OAAO,mBAAmB,YAC1B,OAAO,UAAU,gBAAgB,cACjC,OAAO,UAAU,mBAAmB,cACpC,OAAO,UAAU,qBAAqB,YAEtC,MAAM,IAAI,MACR,qGACF;AAEJ;AAEA,SAAgB,YAAY,gBAA8C;CACxE,qBAAqB,cAAc;CACnC,MAAM,SAAS,eAAe,YAAY;CAC1C,OAAO;EACL,GAAG;EACH,QAAQ,kBAAkB,OAAO,MAAM;CACzC;AACF;AAEA,SAAgB,eAAe,gBAAgC,QAAa;CAC1E,qBAAqB,cAAc;CACnC,OAAO,eAAe,eAAe,MAAM;AAC7C;AAEA,SAAgB,iBACd,gBACqB;CACrB,qBAAqB,cAAc;CACnC,OAAO,eAAe,iBAAiB;AACzC;;;;;;;;AAUA,SAAgB,kBACd,QACY;CACZ,MAAM,SAAqB,CAAC;CAC5B,KAAK,MAAM,OAAO,QAAQ;EACxB,MAAM,QAAQ,OAAO;EAErB,IAAI;GAAC;GAAM,KAAA;GAAW;GAAI,CAAC;GAAG,CAAC;EAAC,CAAC,CAAC,SAAS,KAAK,GAC9C;EAGF,IAAI,MAAM,QAAQ,KAAK,GAOrB,OAAO,OANU,MAAM,KAAK,SAAc;GACxC,IAAI,OAAO,SAAS,UAClB,OAAO,kBAAkB,IAAI;GAE/B,OAAO;EACT,CACqB,CAAC,CAAC,QAAQ,SAAc,SAAS,IAAI;OACrD,IAAI,OAAO,UAAU,UAC1B,OAAO,OAAO,kBAAkB,KAAK;OAErC,OAAO,OAAO;CAElB;CAEA,OAAO;AACT;;;;;AAMA,MAAM,iBAAiB,UACrB,OAAO,UAAU,YACjB,OAAO,UAAU,SAAS,KAAK,KAAK,MAAM;AAE5C,MAAM,WAAW,UAAwB;CAAC;CAAM,KAAA;CAAW;AAAE,CAAC,CAAC,SAAS,KAAK;AAE7E,SAAgB,kBAAiD,QAAc;CAC7E,MAAM,SAAS,EAAE,GAAG,OAAO;CAC3B,KAAK,MAAM,OAAO,QAAQ;EACxB,MAAM,QAAQ,OAAO;EAErB,IAAI,QAAQ,KAAK,GAAG;GAClB,OAAQ,OAAe,KAAA;GACvB;EACF;EAEA,IAAI,MAAM,QAAQ,KAAK,GAErB,OAAO,OADS,OAAO,OAAO,kBAAkB,EAAE,GAAG,MAAM,CAAC,CACxC;OACf,IAAI,cAAc,KAAK,GAE5B,OAAO,OADS,kBAAkB,KACd;OAEpB,OAAO,OAAO;CAElB;CAEA,OAAO;AACT;;;;;AAMA,SAAgB,kBACd,QACe;CACf,IAAI,CAAC,QAAQ,OAAO,CAAC;CAiBrB,OAhBqB,OAClB,KAAK,UAAuB;EAC3B,IAAI,MAAM,QACR,OAAO;GACL,GAAG;GACH,QAAQ,kBAAkB,MAAM,MAAM;EACxC;EAEF,OAAO;CACT,CAAC,CAAC,CACD,MAAM,GAAG,MAAM;EAGd,QAFuB,EAAE,aAAa,SAAS,MAChC,EAAE,aAAa,SAAS;CAEzC,CAEgB;AACpB"}