Source: index.js

import _ from "lodash";

/**
 * 特定のコンポーネントもしくは HTML タグを利用した uiSchema をまとめて生成するクラス
 * @copyright yokra9
 * @license MIT
 */
class UiSchemaGenerator {
  /**
   * @constructor
   * @param {Object} jsonSchema JSON Schema の スキーマ定義部分
   * @property {Object} uiSchema uiSchema
   * @property {Object} schema JSON Schema の スキーマ定義部分
   * @property {Object} fieldOptions デフォルトのデータオブジェクト
   * @property {Object} errorOptions デフォルトのエラーオプション
   * @see <a href="https://json-schema.org/">JSON Schema</a>
   * @see <a href="https://jarvelov.gitbook.io/vue-form-json-schema/api/vue-form-json-schema/ui-schema">uiSchema</a>
   */
  constructor(jsonSchema) {
    this.uiSchema = new Array();
    this.fieldOptions = {};
    this.errorOptions = {};

    if (jsonSchema) {
      this.schema = jsonSchema;
    } else {
      throw new TypeError("スキーマ定義がありません");
    }
  }

  /**
   * デフォルトのデータオブジェクトを追加設定する。
   * @param {Object} fieldOptions データオブジェクト
   * @returns {UiSchemaGenerator} UiSchemaGenerator
   */
  setDefaultFieldOptions(fieldOptions) {
    // 再帰的マージ(Object.assign()は浅いマージ)
    this.fieldOptions = _.merge(this.fieldOptions, fieldOptions);
    return this;
  }

  /**
   * デフォルトのエラーオプションを追加設定する。
   * @param {Object} errorOptions データオブジェクト
   * @returns {UiSchemaGenerator} UiSchemaGenerator
   */
  setDefaultErrorOptions(errorOptions) {
    // 再帰的マージ(Object.assign()は浅いマージ)
    this.errorOptions = _.merge(this.errorOptions, errorOptions);
    return this;
  }

  /**
   * uiSchema を返却する
   * @returns {Array} uiSchema
   */
  toArray() {
    return this.uiSchema;
  }

  /**
   * 特定の要素の uiSchema をまとめて生成する
   * @param {Object|String} component 生成するコンポーネントもしくはHTMLタグ名
   * @param {Array<String>} [models] 要素と紐付けるモデル
   * @param {Object} [fieldOptions] テンプレート内で使う属性に対応するデータオブジェクト。値として function(model, index) を取ることもできる。 {@link https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth 公式の説明はこちら}
   * @param {Object} [displayOptions] 表示するかどうかの条件を JSON Schema で指定する
   * @param {Object} [errorOptions] エラーが発生した時のみ有効になる fieldOptions
   * @param {Array} [children] 子要素
   * @param {boolean} [errorHandler] エラーハンドリングを行うかどうか
   * @returns {UiSchemaGenerator} UiSchemaGenerator
   */
  generate(
    component,
    models,
    fieldOptions,
    children,
    displayOptions,
    errorOptions,
    errorHandler
  ) {
    if (!component) throw new TypeError("引数 component は必須です");

    // モデルが未指定、もしくは空配列のとき
    if (models == null || models.length == 0) {
      this.uiSchema.push(
        // uiSchema
        {
          component,
          fieldOptions: _.mergeWith(
            {},
            // ダイナミックなデフォルト値(setDefaultFieldOptions()で外部から設定可能)
            this.fieldOptions,
            // 引数
            fieldOptions,
            (obj, src) => {
              // modelsにはnull等が入る
              if (typeof src == "function")
                return src(models, this.uiSchema.length);
            }
          ),
          children,
          displayOptions,
          errorHandler,
          errorOptions: _.merge({}, this.errorOptions, errorOptions),
        }
      );
    } // モデルが一つ以上指定されているとき
    else {
      // 全モデルに対して uiSchema を生成する
      models.forEach((model) => {
        this.uiSchema.push(
          // uiSchema
          {
            component,
            model,
            fieldOptions: _.mergeWith(
              {},
              // ダイナミックなデフォルト値(setDefaultFieldOptions()で外部から設定可能)
              this.fieldOptions,
              // 引数
              fieldOptions,
              (obj, src) => {
                if (typeof src == "function")
                  return src(model, this.uiSchema.length);
              }
            ),
            children,
            displayOptions,
            errorHandler,
            errorOptions: _.merge({}, this.errorOptions, errorOptions),
          }
        );
      });
    }
    return this;
  }
}

export default UiSchemaGenerator;