Source: form/transformSchema.js

import { FormElements } from './FormElements.js';
import { markRaw } from 'vue';

/**
 * Transforms a given schema into a normalized
 * form that is easily readable and processable
 * by the AutoForm component and it's children
 * @param value {FormSchema}
 * @param name {string}
 * @return {{component: Raw<unknown>, data: {optional: boolean, type}}}
 */
export const transformSchema = (value, name) => {
  let schema = { ...value };
  if (typeof value === 'function') {
    schema = { type: value, optional: false };
  }
  schema.name = name;
  schema.required = schema.optional !== true || schema.required !== false;
  delete schema.optional;
  schema.formType = getFormType(schema);
  schema.formElement =
    FormElements.get(schema.formType) ?? FormElements.default();
  schema.label = getLabel(schema);
  schema.options = getOptions(schema);
  schema.validate = getValidator(schema);
  const data = ((_schema) => {
    const { type, formType, formElement, data, ...rest } = _schema;
    return { type: formType, ...rest };
  })(schema);

  return {
    data,
    component: markRaw(schema.formElement),
  };
};

const getFormType = ({ formType, type, options, allowedValues }) => {
  if (formType) return formType;

  if (options || allowedValues) {
    return 'select';
  }
  if (Array.isArray(type)) {
    throw new Error('not yet implemented');
  }
  switch (type) {
    case String:
      return 'text';
    case Number:
      return 'number';
    case Boolean:
      return 'checkbox';
    default:
      throw new Error(`unknown type ${type}`);
  }
};

const getLabel = ({ label, name }) => {
  if (label || label === null) return label;
  return (
    name
      // remove whitespace
      .trim()
      // split at any uppercase
      .split(/[A-Z]/g)
      // capitalize
      .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
      // construct label
      .join(' ')
  );
};

const getOptions = ({ formType, options, allowedValues }) => {
  if (options) return options;
  if (allowedValues) {
    return;
  }
  switch (formType) {
    case 'select-radio':
      return [
        {
          value: true,
          label: 'Yes',
        },
        {
          value: false,
          label: 'No',
        },
      ];
  }
};

const getValidator = () => {
  return () => ({ valid: true, errors: [] });
};