# frozen_string_literal: true module ActiveEventStore # RES event wrapper class Event < RubyEventStore::Event RESERVED_ATTRIBUTES = %i[event_id type metadata].freeze class << self attr_writer :identifier def identifier return @identifier if instance_variable_defined?(:@identifier) @identifier = name.underscore.tr("/", ".") end # define store readers def attributes(*fields) fields.each do |field| raise ArgumentError, "#{field} is reserved" if RESERVED_ATTRIBUTES.include?(field) defined_attributes << field class_eval <<~CODE, __FILE__, __LINE__ + 1 def #{field} data[:#{field}] end CODE end end def sync_attributes(*fields) fields.each do |field| raise ArgumentError, "#{field} is reserved" if RESERVED_ATTRIBUTES.include?(field) defined_sync_attributes << field attr_reader field end end def defined_attributes return @defined_attributes if instance_variable_defined?(:@defined_attributes) @defined_attributes = if superclass.respond_to?(:defined_attributes) superclass.defined_attributes.dup else [] end end def defined_sync_attributes return @defined_sync_attributes if instance_variable_defined?(:@defined_sync_attributes) @defined_sync_attributes = if superclass.respond_to?(:defined_sync_attributes) superclass.defined_sync_attributes.dup else [] end end end def initialize(metadata: {}, event_id: nil, **params) validate_attributes!(params) extract_sync_attributes!(params) super(**{event_id: event_id, metadata: metadata, data: params}.compact) end def type self.class.identifier end def inspect "#{self.class.name}<#{type}##{message_id}>, data: #{data}, metadata: #{metadata}" end protected attr_writer :event_id def validate_attributes!(params) unknown_fields = params.keys.map(&:to_sym) - self.class.defined_attributes - self.class.defined_sync_attributes unless unknown_fields.empty? raise ArgumentError, "Unknown event attributes: #{unknown_fields.join(", ")}" end end def extract_sync_attributes!(params) params.keys.each do |key| next unless self.class.defined_sync_attributes.include?(key.to_sym) instance_variable_set(:"@#{key}", params.delete(key)) end end end end