# frozen_string_literal: true require 'roda/endpoints' require 'roda/endpoints/endpoint/class_interface' require 'roda/endpoints/endpoint/lookup' require 'roda/endpoints/endpoint/namespace' require 'roda/endpoints/endpoint/transactions' require 'roda/endpoints/endpoint/validations' require 'roda/endpoints/endpoint/verbs' require 'dry/monads' class Roda module Endpoints # Generic HTTP endpoint abstraction. class Endpoint extend ClassInterface include Dry::Monads::Either::Mixin autoload :Collection, 'roda/endpoints/endpoint/collection' autoload :Item, 'roda/endpoints/endpoint/item' autoload :Singleton, 'roda/endpoints/endpoint/singleton' self.attributes = %i(container type).freeze self.defaults = EMPTY_HASH self.statuses = { get: { success: :ok, failure: :not_found }, put: { success: :accepted, failure: :unprocessable_entity }, post: { success: :created, failure: :unprocessable_entity }, patch: { success: :accepted, failure: :unprocessable_entity }, delete: { success: :no_content, failure: :unprocessable_entity } }.freeze self.verbs = EMPTY_SET # @param attributes [{Symbol=>Object}] def initialize(**attributes) self.class.defaults.merge(attributes).each do |key, value| singleton_class.define_attribute(key) unless respond_to?(key) instance_variable_set(:"@#{key}", value) end end prepend Namespace prepend Verbs prepend Validations include Transactions prepend Lookup attr_accessor :captures # @return [Symbol] def type self.class.type end # @param type [:collection, :item] # @param attributes [{Symbol=>Object}] def with(type: self.class, **attributes) type.new to_hash.merge(attributes).merge(inheritable_attributes) end # @param [Class(Endpoint)] type # @param [Hash] params def child(type: Singleton, **params) with(type: type, **params) end # @return [{Symbol=>Object}] def inheritable_attributes { parent: self, container: container } end # @return [Proc] def route prepare_validations! prepare_verbs! self.class.route end # @return [{Symbol=>Object}] def to_hash self.class.attributes.each_with_object({}) do |name, hash| hash[name] = public_send(name) end end end end end