module Plumb::Attributes::ClassMethods

def attribute(name, type = Types::Any, writer: false, &block)


attribute(:friends, [Person])
attribute(:friends, Types::Array[Person])
attribute(:friends, []) # same as Types::Array[Types::Any]
attribute(:friends, Types::Array) # same as Types::Array[Types::Any]
attribute(:friends, Types::Array) { attribute(:name, String) }
attribute(:name, String)
attribute(:friend, MyStruct) { attribute(:name, String) }
attribute(:friend) { attribute(:name, String) }
def attribute(name, type = Types::Any, writer: false, &block)
  key = Key.wrap(name)
  name = key.to_sym
  type = Composable.wrap(type)
  if block_given? # :foo, Array[Data] or :foo, Struct
    type = __plumb_struct_class__ if type == Types::Any
    type = Plumb.decorate(type) do |node|
      if node.is_a?(Plumb::ArrayClass)
        child = node.children.first
        child = __plumb_struct_class__ if child == Types::Any
        Types::Array[build_nested(name, child, &block)]
      elsif node.is_a?(Plumb::Step)
        build_nested(name, node, &block)
      elsif node.is_a?(Class) && node <= Plumb::Attributes
        build_nested(name, node, &block)
      else
        node
      end
    end
  end
  @_schema = _schema + { key => type }
  __plumb_define_attribute_reader_method__(name)
  return name unless writer
  __plumb_define_attribute_writer_method__(name)
end