smart_domain 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +65 -0
- data/CHANGELOG.md +6 -8
- data/README.md +52 -0
- data/Rakefile +3 -3
- data/lib/generators/{active_domain → smart_domain}/domain/domain_generator.rb +16 -16
- data/lib/generators/{active_domain → smart_domain}/domain/templates/events/created_event.rb.tt +1 -1
- data/lib/generators/{active_domain → smart_domain}/domain/templates/events/deleted_event.rb.tt +1 -1
- data/lib/generators/{active_domain → smart_domain}/domain/templates/events/updated_event.rb.tt +2 -2
- data/lib/generators/{active_domain → smart_domain}/domain/templates/service.rb.tt +5 -5
- data/lib/generators/{active_domain → smart_domain}/domain/templates/setup.rb.tt +4 -4
- data/lib/generators/{active_domain → smart_domain}/install/install_generator.rb +13 -13
- data/lib/smart_domain/configuration.rb +1 -1
- data/lib/smart_domain/domain/exceptions.rb +2 -2
- data/lib/smart_domain/domain/service.rb +1 -1
- data/lib/smart_domain/event/adapters/memory.rb +24 -9
- data/lib/smart_domain/event/base.rb +26 -13
- data/lib/smart_domain/event/handler.rb +5 -3
- data/lib/smart_domain/event/mixins.rb +11 -1
- data/lib/smart_domain/event/registration.rb +4 -4
- data/lib/smart_domain/generators/domain_generator.rb +1 -1
- data/lib/smart_domain/generators/install_generator.rb +1 -1
- data/lib/smart_domain/handlers/audit_handler.rb +22 -24
- data/lib/smart_domain/handlers/metrics_handler.rb +8 -1
- data/lib/smart_domain/integration/active_record.rb +6 -8
- data/lib/smart_domain/railtie.rb +24 -24
- data/lib/smart_domain/tasks/domains.rake +18 -14
- data/lib/smart_domain/version.rb +1 -1
- data/lib/smart_domain.rb +20 -20
- data/smart_domain.gemspec +26 -25
- metadata +32 -43
- data/examples/blog_app/.kamal/hooks/docker-setup.sample +0 -3
- data/examples/blog_app/.kamal/hooks/post-app-boot.sample +0 -3
- data/examples/blog_app/.kamal/hooks/post-deploy.sample +0 -14
- data/examples/blog_app/.kamal/hooks/post-proxy-reboot.sample +0 -3
- data/examples/blog_app/.kamal/hooks/pre-app-boot.sample +0 -3
- data/examples/blog_app/.kamal/hooks/pre-build.sample +0 -51
- data/examples/blog_app/.kamal/hooks/pre-connect.sample +0 -47
- data/examples/blog_app/.kamal/hooks/pre-deploy.sample +0 -122
- data/examples/blog_app/.kamal/hooks/pre-proxy-reboot.sample +0 -3
- data/examples/blog_app/.kamal/secrets +0 -20
- data/examples/blog_app/bin/kamal +0 -27
- data/examples/blog_app/config/deploy.yml +0 -120
- data/examples/blog_app/config/master.key +0 -1
- /data/examples/blog_app/config/initializers/{active_domain.rb → smart_domain.rb} +0 -0
- /data/lib/generators/{active_domain → smart_domain}/domain/templates/policy.rb.tt +0 -0
- /data/lib/generators/{active_domain → smart_domain}/install/templates/README +0 -0
- /data/lib/generators/{active_domain → smart_domain}/install/templates/application_event.rb +0 -0
- /data/lib/generators/{active_domain → smart_domain}/install/templates/application_policy.rb +0 -0
- /data/lib/generators/{active_domain → smart_domain}/install/templates/application_service.rb +0 -0
- /data/lib/generators/{active_domain → smart_domain}/install/templates/initializer.rb +0 -0
|
@@ -37,7 +37,7 @@ module SmartDomain
|
|
|
37
37
|
# @param event [SmartDomain::Event::Base] Event to handle
|
|
38
38
|
# @raise [NotImplementedError] If not implemented by subclass
|
|
39
39
|
def handle(event)
|
|
40
|
-
raise NotImplementedError,
|
|
40
|
+
raise NotImplementedError, 'Subclasses must implement #handle(event)'
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
# Check if this handler can handle a specific event type
|
|
@@ -48,7 +48,7 @@ module SmartDomain
|
|
|
48
48
|
# @param event_type [String] Event type to check
|
|
49
49
|
# @return [Boolean] True if handler can handle this event type
|
|
50
50
|
def can_handle?(event_type)
|
|
51
|
-
raise NotImplementedError,
|
|
51
|
+
raise NotImplementedError, 'Subclasses must implement #can_handle?(event_type)'
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Handle event asynchronously using ActiveJob
|
|
@@ -58,12 +58,14 @@ module SmartDomain
|
|
|
58
58
|
#
|
|
59
59
|
# @param event [SmartDomain::Event::Base] Event to handle
|
|
60
60
|
# @raise [RuntimeError] If ActiveJob is not loaded
|
|
61
|
+
# @raise [ValidationError] If event is invalid
|
|
61
62
|
def handle_async(event)
|
|
62
63
|
unless defined?(ActiveJob)
|
|
63
64
|
raise "ActiveJob is required for async event handling. Please require 'active_job' in your application."
|
|
64
65
|
end
|
|
65
66
|
|
|
66
|
-
event.
|
|
67
|
+
raise ValidationError, "Event validation failed: #{event.errors.full_messages.join(', ')}" unless event.valid?
|
|
68
|
+
|
|
67
69
|
HandlerJob.perform_later(self.class.name, event.to_h)
|
|
68
70
|
end
|
|
69
71
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'active_support/concern'
|
|
4
4
|
|
|
5
5
|
module SmartDomain
|
|
6
6
|
module Event
|
|
@@ -89,6 +89,14 @@ module SmartDomain
|
|
|
89
89
|
attribute :changed_fields, default: -> { [] }
|
|
90
90
|
attribute :old_values, default: -> { {} }
|
|
91
91
|
attribute :new_values, default: -> { {} }
|
|
92
|
+
|
|
93
|
+
validate :changed_fields_must_not_be_empty
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def changed_fields_must_not_be_empty
|
|
98
|
+
errors.add(:changed_fields, "can't be blank") if changed_fields.blank? || changed_fields.empty?
|
|
99
|
+
end
|
|
92
100
|
end
|
|
93
101
|
|
|
94
102
|
# Helper to extract changes from an ActiveRecord model
|
|
@@ -150,6 +158,8 @@ module SmartDomain
|
|
|
150
158
|
|
|
151
159
|
included do
|
|
152
160
|
attribute :reason, :string
|
|
161
|
+
|
|
162
|
+
validates :reason, presence: true
|
|
153
163
|
end
|
|
154
164
|
end
|
|
155
165
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
3
|
+
require_relative '../handlers/audit_handler'
|
|
4
|
+
require_relative '../handlers/metrics_handler'
|
|
5
5
|
|
|
6
6
|
module SmartDomain
|
|
7
7
|
module Event
|
|
@@ -86,8 +86,8 @@ module SmartDomain
|
|
|
86
86
|
# Log what was registered
|
|
87
87
|
if include_audit || include_metrics
|
|
88
88
|
handlers_registered = []
|
|
89
|
-
handlers_registered <<
|
|
90
|
-
handlers_registered <<
|
|
89
|
+
handlers_registered << 'audit' if include_audit
|
|
90
|
+
handlers_registered << 'metrics' if include_metrics
|
|
91
91
|
|
|
92
92
|
logger.info "[SmartDomain::Registration] Standard handlers registered for #{domain} domain: " \
|
|
93
93
|
"#{handlers_registered.join(', ')} (#{events.size} events)"
|
|
@@ -41,7 +41,7 @@ module SmartDomain
|
|
|
41
41
|
# @param event_type [String] Event type to check
|
|
42
42
|
# @return [Boolean] True if event belongs to this domain
|
|
43
43
|
def can_handle?(event_type)
|
|
44
|
-
return true if @domain ==
|
|
44
|
+
return true if @domain == '*'
|
|
45
45
|
|
|
46
46
|
event_type.start_with?("#{@domain}.")
|
|
47
47
|
end
|
|
@@ -49,7 +49,7 @@ module SmartDomain
|
|
|
49
49
|
# Handle audit logging for an event
|
|
50
50
|
# @param event [SmartDomain::Event::Base] Event to audit
|
|
51
51
|
def handle(event)
|
|
52
|
-
action = event.event_type.split(
|
|
52
|
+
action = event.event_type.split('.').last
|
|
53
53
|
|
|
54
54
|
# 1. Log to Rails logger (structured)
|
|
55
55
|
log_audit_event(event, action)
|
|
@@ -117,17 +117,15 @@ module SmartDomain
|
|
|
117
117
|
return unless defined?(AuditEvent)
|
|
118
118
|
|
|
119
119
|
AuditEvent.create!(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
event_id: event.event_id,
|
|
121
|
+
event_type: event.event_type,
|
|
122
|
+
aggregate_id: event.aggregate_id,
|
|
123
|
+
aggregate_type: event.aggregate_type,
|
|
123
124
|
organization_id: event.organization_id,
|
|
124
|
-
|
|
125
|
-
user_agent: extract_user_agent(event),
|
|
126
|
-
old_values: extract_old_values(event),
|
|
127
|
-
new_values: extract_new_values(event),
|
|
128
|
-
occurred_at: event.occurred_at,
|
|
125
|
+
category: map_event_category(event.event_type),
|
|
129
126
|
risk_level: assess_risk_level(event.event_type),
|
|
130
|
-
|
|
127
|
+
event_data: event.to_h,
|
|
128
|
+
occurred_at: event.occurred_at
|
|
131
129
|
)
|
|
132
130
|
rescue StandardError => e
|
|
133
131
|
@logger.warn "[SmartDomain::AuditHandler] Failed to write to audit table: #{e.message}"
|
|
@@ -138,14 +136,14 @@ module SmartDomain
|
|
|
138
136
|
# @return [String] Audit category
|
|
139
137
|
def map_event_category(event_type)
|
|
140
138
|
case event_type
|
|
141
|
-
when /^auth
|
|
142
|
-
|
|
139
|
+
when /^auth\.|logged_in|logged_out|login|logout|authenticated|password/
|
|
140
|
+
'authentication'
|
|
143
141
|
when /accessed|viewed|patient\./
|
|
144
|
-
|
|
142
|
+
'data_access'
|
|
145
143
|
when /created|updated|deleted|assigned|removed/
|
|
146
|
-
|
|
144
|
+
'admin_action'
|
|
147
145
|
else
|
|
148
|
-
|
|
146
|
+
'system_event'
|
|
149
147
|
end
|
|
150
148
|
end
|
|
151
149
|
|
|
@@ -155,11 +153,11 @@ module SmartDomain
|
|
|
155
153
|
def assess_risk_level(event_type)
|
|
156
154
|
case event_type
|
|
157
155
|
when /suspended|deleted|revoked|failed|rejected/
|
|
158
|
-
|
|
156
|
+
'HIGH'
|
|
159
157
|
when /updated|changed|assigned/
|
|
160
|
-
|
|
158
|
+
'MEDIUM'
|
|
161
159
|
else
|
|
162
|
-
|
|
160
|
+
'LOW'
|
|
163
161
|
end
|
|
164
162
|
end
|
|
165
163
|
|
|
@@ -167,35 +165,35 @@ module SmartDomain
|
|
|
167
165
|
# @param event [SmartDomain::Event::Base] Event
|
|
168
166
|
# @return [String, nil] Actor ID
|
|
169
167
|
def extract_actor_id(event)
|
|
170
|
-
event.try(:actor_id) || event.attributes[
|
|
168
|
+
event.try(:actor_id) || event.attributes['actor_id']
|
|
171
169
|
end
|
|
172
170
|
|
|
173
171
|
# Extract ip_address from event (SecurityContextMixin)
|
|
174
172
|
# @param event [SmartDomain::Event::Base] Event
|
|
175
173
|
# @return [String, nil] IP address
|
|
176
174
|
def extract_ip_address(event)
|
|
177
|
-
event.try(:ip_address) || event.attributes[
|
|
175
|
+
event.try(:ip_address) || event.attributes['ip_address']
|
|
178
176
|
end
|
|
179
177
|
|
|
180
178
|
# Extract user_agent from event (SecurityContextMixin)
|
|
181
179
|
# @param event [SmartDomain::Event::Base] Event
|
|
182
180
|
# @return [String, nil] User agent
|
|
183
181
|
def extract_user_agent(event)
|
|
184
|
-
event.try(:user_agent) || event.attributes[
|
|
182
|
+
event.try(:user_agent) || event.attributes['user_agent']
|
|
185
183
|
end
|
|
186
184
|
|
|
187
185
|
# Extract old_values from event (ChangeTrackingMixin)
|
|
188
186
|
# @param event [SmartDomain::Event::Base] Event
|
|
189
187
|
# @return [Hash, nil] Old values
|
|
190
188
|
def extract_old_values(event)
|
|
191
|
-
event.try(:old_values) || event.attributes[
|
|
189
|
+
event.try(:old_values) || event.attributes['old_values']
|
|
192
190
|
end
|
|
193
191
|
|
|
194
192
|
# Extract new_values from event (ChangeTrackingMixin)
|
|
195
193
|
# @param event [SmartDomain::Event::Base] Event
|
|
196
194
|
# @return [Hash, nil] New values
|
|
197
195
|
def extract_new_values(event)
|
|
198
|
-
event.try(:new_values) || event.attributes[
|
|
196
|
+
event.try(:new_values) || event.attributes['new_values']
|
|
199
197
|
end
|
|
200
198
|
|
|
201
199
|
# Build compliance flags for audit record
|
|
@@ -36,7 +36,7 @@ module SmartDomain
|
|
|
36
36
|
# @param event_type [String] Event type to check
|
|
37
37
|
# @return [Boolean] True if event belongs to this domain
|
|
38
38
|
def can_handle?(event_type)
|
|
39
|
-
return true if @domain ==
|
|
39
|
+
return true if @domain == '*'
|
|
40
40
|
|
|
41
41
|
event_type.start_with?("#{@domain}.")
|
|
42
42
|
end
|
|
@@ -47,7 +47,14 @@ module SmartDomain
|
|
|
47
47
|
metric_name = build_metric_name(event)
|
|
48
48
|
tags = build_metric_tags(event)
|
|
49
49
|
|
|
50
|
+
# Emit counter metric
|
|
50
51
|
emit_metric(metric_name, tags)
|
|
52
|
+
|
|
53
|
+
# Emit timing metric if duration is present
|
|
54
|
+
if event.respond_to?(:duration) && event.duration
|
|
55
|
+
timing_name = "#{metric_name}.duration"
|
|
56
|
+
emit_metric(timing_name, tags.merge(duration_ms: event.duration))
|
|
57
|
+
end
|
|
51
58
|
rescue StandardError => e
|
|
52
59
|
# Never fail on metrics handler errors
|
|
53
60
|
@logger.warn "[SmartDomain::MetricsHandler] Metrics collection failed: #{e.message}"
|
|
@@ -145,14 +145,12 @@ module SmartDomain
|
|
|
145
145
|
return if @pending_domain_events.blank?
|
|
146
146
|
|
|
147
147
|
@pending_domain_events.each do |event|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
logger.error e.backtrace.join("\n")
|
|
155
|
-
end
|
|
148
|
+
SmartDomain::Event.bus.publish(event)
|
|
149
|
+
rescue StandardError => e
|
|
150
|
+
# Log error but don't raise (events should be fire-and-forget)
|
|
151
|
+
logger = defined?(Rails) ? Rails.logger : Logger.new($stdout)
|
|
152
|
+
logger.error "[SmartDomain] Failed to publish event: #{e.message}"
|
|
153
|
+
logger.error e.backtrace.join("\n")
|
|
156
154
|
end
|
|
157
155
|
|
|
158
156
|
clear_domain_events
|
data/lib/smart_domain/railtie.rb
CHANGED
|
@@ -12,8 +12,8 @@ module SmartDomain
|
|
|
12
12
|
|
|
13
13
|
# Add generators to load path
|
|
14
14
|
generators do
|
|
15
|
-
require_relative
|
|
16
|
-
require_relative
|
|
15
|
+
require_relative 'generators/install_generator'
|
|
16
|
+
require_relative 'generators/domain_generator'
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# Configuration hook
|
|
@@ -27,35 +27,35 @@ module SmartDomain
|
|
|
27
27
|
|
|
28
28
|
# Rake tasks
|
|
29
29
|
rake_tasks do
|
|
30
|
-
load
|
|
30
|
+
load 'smart_domain/tasks/domains.rake'
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
private
|
|
34
|
-
|
|
35
33
|
# Load all domain setup files
|
|
36
34
|
def self.load_domain_setups
|
|
37
|
-
setup_files = Dir[Rails.root.join(
|
|
35
|
+
setup_files = Dir[Rails.root.join('app/domains/**/setup.rb')]
|
|
38
36
|
|
|
39
37
|
setup_files.each do |setup_file|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Rails.logger.
|
|
56
|
-
Rails.logger.error e.message
|
|
57
|
-
Rails.logger.error e.backtrace.join("\n")
|
|
38
|
+
require setup_file
|
|
39
|
+
|
|
40
|
+
# Extract domain module name from path
|
|
41
|
+
# e.g., app/domains/user_management/setup.rb -> UserManagement
|
|
42
|
+
domain_path = setup_file.gsub(Rails.root.join('app/domains/').to_s, '')
|
|
43
|
+
domain_name = domain_path.split('/').first.camelize
|
|
44
|
+
|
|
45
|
+
# Call setup! method if defined
|
|
46
|
+
domain_module = begin
|
|
47
|
+
domain_name.constantize
|
|
48
|
+
rescue StandardError
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
if domain_module.respond_to?(:setup!)
|
|
52
|
+
domain_module.setup!
|
|
53
|
+
Rails.logger.info "[SmartDomain] Loaded domain: #{domain_name}"
|
|
58
54
|
end
|
|
55
|
+
rescue StandardError => e
|
|
56
|
+
Rails.logger.error "[SmartDomain] Failed to load domain setup: #{setup_file}"
|
|
57
|
+
Rails.logger.error e.message
|
|
58
|
+
Rails.logger.error e.backtrace.join("\n")
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
end
|
|
@@ -1,43 +1,47 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
namespace :active_domain do
|
|
4
|
-
desc
|
|
4
|
+
desc 'List all registered domains'
|
|
5
5
|
task domains: :environment do
|
|
6
|
-
setup_files = Dir[Rails.root.join(
|
|
6
|
+
setup_files = Dir[Rails.root.join('app/domains/**/setup.rb')]
|
|
7
7
|
|
|
8
8
|
if setup_files.empty?
|
|
9
|
-
puts
|
|
10
|
-
puts
|
|
9
|
+
puts 'No domains found in app/domains/'
|
|
10
|
+
puts 'Generate your first domain with: rails generate active_domain:domain User'
|
|
11
11
|
else
|
|
12
|
-
puts
|
|
12
|
+
puts 'Registered domains:'
|
|
13
13
|
setup_files.each do |setup_file|
|
|
14
|
-
domain_path = setup_file.gsub(Rails.root.join(
|
|
15
|
-
domain_name = domain_path.split(
|
|
14
|
+
domain_path = setup_file.gsub(Rails.root.join('app/domains/').to_s, '')
|
|
15
|
+
domain_name = domain_path.split('/').first
|
|
16
16
|
puts " - #{domain_name}"
|
|
17
17
|
end
|
|
18
18
|
puts "\nTotal: #{setup_files.size} domain(s)"
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
desc
|
|
22
|
+
desc 'Reload all domain setups'
|
|
23
23
|
task reload: :environment do
|
|
24
|
-
setup_files = Dir[Rails.root.join(
|
|
24
|
+
setup_files = Dir[Rails.root.join('app/domains/**/setup.rb')]
|
|
25
25
|
|
|
26
26
|
puts "Reloading #{setup_files.size} domain(s)..."
|
|
27
27
|
|
|
28
28
|
setup_files.each do |setup_file|
|
|
29
29
|
load setup_file
|
|
30
30
|
|
|
31
|
-
domain_path = setup_file.gsub(Rails.root.join(
|
|
32
|
-
domain_name = domain_path.split(
|
|
31
|
+
domain_path = setup_file.gsub(Rails.root.join('app/domains/').to_s, '')
|
|
32
|
+
domain_name = domain_path.split('/').first.camelize
|
|
33
33
|
|
|
34
|
-
domain_module =
|
|
35
|
-
|
|
34
|
+
domain_module = begin
|
|
35
|
+
domain_name.constantize
|
|
36
|
+
rescue StandardError
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
if domain_module.respond_to?(:setup!)
|
|
36
40
|
domain_module.setup!
|
|
37
41
|
puts " ✓ #{domain_name}"
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
|
|
41
|
-
puts
|
|
45
|
+
puts 'Done!'
|
|
42
46
|
end
|
|
43
47
|
end
|
data/lib/smart_domain/version.rb
CHANGED
data/lib/smart_domain.rb
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
3
|
+
require 'active_model'
|
|
4
|
+
require 'active_support'
|
|
5
|
+
require 'active_support/core_ext'
|
|
6
|
+
require 'active_record'
|
|
7
|
+
require 'logger'
|
|
8
8
|
|
|
9
|
-
require_relative
|
|
10
|
-
require_relative
|
|
9
|
+
require_relative 'smart_domain/version'
|
|
10
|
+
require_relative 'smart_domain/configuration'
|
|
11
11
|
|
|
12
12
|
# Event system
|
|
13
|
-
require_relative
|
|
14
|
-
require_relative
|
|
15
|
-
require_relative
|
|
16
|
-
require_relative
|
|
13
|
+
require_relative 'smart_domain/event/base'
|
|
14
|
+
require_relative 'smart_domain/event/mixins'
|
|
15
|
+
require_relative 'smart_domain/event/handler'
|
|
16
|
+
require_relative 'smart_domain/event/adapters/memory'
|
|
17
17
|
|
|
18
18
|
# Handlers
|
|
19
|
-
require_relative
|
|
20
|
-
require_relative
|
|
19
|
+
require_relative 'smart_domain/handlers/audit_handler'
|
|
20
|
+
require_relative 'smart_domain/handlers/metrics_handler'
|
|
21
21
|
|
|
22
22
|
# Event registration
|
|
23
|
-
require_relative
|
|
23
|
+
require_relative 'smart_domain/event/registration'
|
|
24
24
|
|
|
25
25
|
# Domain patterns
|
|
26
|
-
require_relative
|
|
27
|
-
require_relative
|
|
28
|
-
require_relative
|
|
26
|
+
require_relative 'smart_domain/domain/exceptions'
|
|
27
|
+
require_relative 'smart_domain/domain/policy'
|
|
28
|
+
require_relative 'smart_domain/domain/service'
|
|
29
29
|
|
|
30
30
|
# Rails integration
|
|
31
|
-
require_relative
|
|
32
|
-
require_relative
|
|
31
|
+
require_relative 'smart_domain/integration/active_record'
|
|
32
|
+
require_relative 'smart_domain/integration/multi_tenancy'
|
|
33
33
|
|
|
34
34
|
# Railtie (loads automatically if Rails is present)
|
|
35
|
-
require_relative
|
|
35
|
+
require_relative 'smart_domain/railtie' if defined?(Rails::Railtie)
|
|
36
36
|
|
|
37
37
|
# SmartDomain - Domain-Driven Design and Event-Driven Architecture for Rails
|
|
38
38
|
#
|
data/smart_domain.gemspec
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative 'lib/smart_domain/version'
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name =
|
|
6
|
+
spec.name = 'smart_domain'
|
|
7
7
|
spec.version = SmartDomain::VERSION
|
|
8
|
-
spec.authors = [
|
|
9
|
-
spec.email = [
|
|
8
|
+
spec.authors = ['Rachid Al Maach']
|
|
9
|
+
spec.email = ['rachid@qraft.nl']
|
|
10
10
|
|
|
11
|
-
spec.summary =
|
|
11
|
+
spec.summary = 'Smart Domain-Driven Design and Event-Driven Architecture for Rails'
|
|
12
12
|
spec.description = <<~DESC
|
|
13
13
|
SmartDomain brings battle-tested DDD/EDA patterns to Rails applications.
|
|
14
14
|
Inspired by the Aeyes healthcare platform, it provides domain events,
|
|
@@ -16,13 +16,14 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
Features 70% boilerplate reduction through intelligent event handling and
|
|
17
17
|
AI-augmented development patterns.
|
|
18
18
|
DESC
|
|
19
|
-
spec.homepage =
|
|
20
|
-
spec.license =
|
|
21
|
-
spec.required_ruby_version =
|
|
19
|
+
spec.homepage = 'https://github.com/rachid/smart_domain'
|
|
20
|
+
spec.license = 'MIT'
|
|
21
|
+
spec.required_ruby_version = '>= 3.0.0'
|
|
22
22
|
|
|
23
|
-
spec.metadata[
|
|
24
|
-
spec.metadata[
|
|
25
|
-
spec.metadata[
|
|
23
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
24
|
+
spec.metadata['source_code_uri'] = 'https://github.com/rachid/smart_domain'
|
|
25
|
+
spec.metadata['changelog_uri'] = 'https://github.com/rachid/smart_domain/blob/main/CHANGELOG.md'
|
|
26
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
26
27
|
|
|
27
28
|
spec.files = Dir.chdir(__dir__) do
|
|
28
29
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
@@ -31,23 +32,23 @@ Gem::Specification.new do |spec|
|
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
spec.bindir =
|
|
35
|
+
spec.bindir = 'exe'
|
|
35
36
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
36
|
-
spec.require_paths = [
|
|
37
|
+
spec.require_paths = ['lib']
|
|
37
38
|
|
|
38
39
|
# Core dependencies
|
|
39
|
-
spec.add_dependency
|
|
40
|
-
spec.add_dependency
|
|
41
|
-
spec.add_dependency
|
|
42
|
-
spec.add_dependency
|
|
40
|
+
spec.add_dependency 'activemodel', '>= 7.0'
|
|
41
|
+
spec.add_dependency 'activerecord', '>= 7.0'
|
|
42
|
+
spec.add_dependency 'activesupport', '>= 7.0'
|
|
43
|
+
spec.add_dependency 'rails', '>= 7.0'
|
|
43
44
|
|
|
44
45
|
# Development dependencies
|
|
45
|
-
spec.add_development_dependency
|
|
46
|
-
spec.add_development_dependency
|
|
47
|
-
spec.add_development_dependency
|
|
48
|
-
spec.add_development_dependency
|
|
49
|
-
spec.add_development_dependency
|
|
50
|
-
spec.add_development_dependency
|
|
51
|
-
spec.add_development_dependency
|
|
52
|
-
spec.add_development_dependency
|
|
46
|
+
spec.add_development_dependency 'factory_bot_rails', '~> 6.2'
|
|
47
|
+
spec.add_development_dependency 'faker', '~> 3.2'
|
|
48
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
|
49
|
+
spec.add_development_dependency 'rspec-rails', '~> 6.0'
|
|
50
|
+
spec.add_development_dependency 'rubocop', '~> 1.50'
|
|
51
|
+
spec.add_development_dependency 'rubocop-rails', '~> 2.19'
|
|
52
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.20'
|
|
53
|
+
spec.add_development_dependency 'sqlite3', '>= 2.1'
|
|
53
54
|
end
|