 
   for type <- @schema_types do
     def new(unquote(type), opts),
-      do: {unquote(type), opts} |> schema() |> create()
+      do: {unquote(type), opts} |> schema([]) |> create()
   end
 
   for keyword <- @schema_keywords do

  #
  # function: schema
  #
  @spec schema(any) :: Xema.Schema.t()

  defp schema(list) when is_list(list) do
    case Keyword.keyword?(list) do
      true ->
        schema({:any, list})

      false ->
        schema({list, []})
    end
  end

  defp schema(value) when not is_tuple(value), do: schema({value, []})

  defp schema({:ref, pointer}), do: Ref.new(pointer)

  defp schema({list, keywords}) when is_list(list),
    do:
      keywords
      |> Keyword.put(:type, list)
      |> update()
      |> Schema.new()

  for type <- @schema_types do
    defp schema({unquote(type), keywords}) when is_list(keywords) do
      keywords = Keyword.put(keywords, :type, unquote(type))
      # IO.inspect keywords[:id], label: :id

      case SchemaValidator.validate(unquote(type), keywords) do
        :ok -> keywords |> update() |> Schema.new()
        {:error, msg} -> raise SchemaError, message: msg
      end
    end

    defp schema({unquote(type), _keywords}) do
      raise SchemaError,
        message: "Wrong argument for #{inspect(unquote(type))}."
    end
  end

  for keyword <- @schema_keywords do
    defp schema({unquote(keyword), keywords}),
      do: schema({:any, [{unquote(keyword), keywords}]})
  end

  defp schema({bool, _})
       when is_boolean(bool),
       do: Schema.new(type: bool)

  defp schema({type, _}) do
    raise SchemaError,
      message: "#{inspect(type)} is not a valid type or keyword."
  end

  # function: update/1
  #
  @spec update(keyword) :: keyword
  defp update(keywords) do
    keywords
    |> Keyword.put_new(:as, keywords[:type])
    |> Keyword.update(:additional_items, nil, &bool_or_schema/1)
    |> Keyword.update(:additional_properties, nil, &bool_or_schema/1)
    |> Keyword.update(:all_of, nil, &schemas/1)
    |> Keyword.update(:any_of, nil, &schemas/1)
    |> Keyword.update(:dependencies, nil, &dependencies/1)
    |> Keyword.update(:items, nil, &items/1)
    |> Keyword.update(:not, nil, &schema(&1))
    |> Keyword.update(:one_of, nil, &schemas/1)
    |> Keyword.update(:pattern_properties, nil, &properties/1)
    |> Keyword.update(:properties, nil, &properties/1)
    |> Keyword.update(:definitions, nil, &properties/1)
    |> Keyword.update(:required, nil, &MapSet.new/1)
    |> update_allow()
  end

  @spec schemas(list) :: list
  defp schemas(list), do: Enum.map(list, fn schema -> schema(schema) end)

  @spec properties(map) :: map
  defp properties(map),
    do: Enum.into(map, %{}, fn {key, prop} -> {key, schema(prop)} end)

  @spec dependencies(map) :: map
  defp dependencies(map),
    do:
      Enum.into(map, %{}, fn
        {key, dep} when is_list(dep) -> {key, dep}
        {key, dep} when is_boolean(dep) -> {key, schema(dep)}
        {key, dep} when is_atom(dep) -> {key, [dep]}
        {key, dep} when is_binary(dep) -> {key, [dep]}
        {key, dep} -> {key, schema(dep)}
      end)

  @spec bool_or_schema(boolean | atom) :: boolean | Xema.Schema.t()
  defp bool_or_schema(bool) when is_boolean(bool), do: bool

  defp bool_or_schema(schema), do: schema(schema)

  @spec items(any) :: list
  defp items(schema) when is_atom(schema) or is_tuple(schema),
    do: schema(schema)

  defp items(schemas) when is_list(schemas), do: schemas(schemas)

  defp items(items), do: items

  defp update_allow(opts) do
    case Keyword.get(opts, :allow, :undefined) do

  defp new_multi_type(list, keywords) when is_list(list) do
    case Enum.all?(list, fn type -> type in @schema_types end) do
      true ->
        {list, keywords} |> schema([]) |> create()

      false ->
        raise(
