nucleus-core 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cad40c45a637495932d264dfef04ca978e3f47dba177e8acbfbd59a37e0c2217
4
- data.tar.gz: 3389a5a8e8bb3d63c4afb7fb47ae900367295d86c7bb4ccf651773b1805ca9b2
3
+ metadata.gz: 16856ef31bb784d60c0245dc2b64688edffafedc629346e4b0aa5ad85c67f03b
4
+ data.tar.gz: 6132356105d16688ba22fcb6ab4827727584660867ffd07b37f2c559d6a365c8
5
5
  SHA512:
6
- metadata.gz: 461315b12ca674353043961e25e49498878392b89d4aef410aa1e0d16e43938087e4eb377840dd4b815d4a176e3f8f09c296be096198dcd39022b647cee4b89a
7
- data.tar.gz: 6cbd15c2ce8e2d264ecdd849e1f723b60519c132e2b422f9fc9857f0fc9828649b712bed93bf90680d1a422e87d25e6277fb801dd457436e39667665f390b3c4
6
+ metadata.gz: 9d77daf39dac0313f1fae986f124394e3f1af56fb1c0a8324a2054398d9c43715df25513a3cc568150ae5eed87bdabd8def043f6542fccce443334b2ee5fdc8b
7
+ data.tar.gz: 7a233128785f6359cd01c351c6fc3633de18af631ea022aa42e73e978c37a59fecab0eaa770d482257ee6c4042182555f94a3ecc3058819df769b2ec2a12bc25
data/README.md CHANGED
@@ -4,18 +4,18 @@
4
4
  [![Circle](https://circleci.com/gh/dodgerogers/nucleus-core/tree/main.svg?style=shield)](https://app.circleci.com/pipelines/github/dodgerogers/nucleus-core?branch=main)
5
5
  [![Code Climate](https://codeclimate.com/github/dodgerogers/nucleus-core/badges/gpa.svg)](https://codeclimate.com/github/dodgerogers/nucleus-core)
6
6
 
7
- NucleusCore Core is a framework to express and orchestrate business logic in a way that is agnostic to the framework.
7
+ NucleusCore Core is a set of components which express and orchestrate business logic separatley to the framework.
8
8
 
9
- ## This gem is still very much in development. A `nucleus-rails` gem will handle the adaptation of NucleusCore::View objects to the rails rendering methods.
9
+ ## This gem is still very much in development. See `nucleus-rails` for Rails usage.
10
10
 
11
11
  Here are the classes NucleusCore exposes, they have preordained responsibilities, can be composed together, and tested simply in isolation from the framework.
12
12
 
13
- - Policy (Authorization) - Can this user perform this process?
14
- - Operation (Services) - Executes a single unit of business logic, or side effect (ScheduleAppointment, CancelOrder, UpdateAddress).
15
- - Workflow (Service Orchestration) - Excecutes multiple units of work, and side effects (ApproveLoan, TakePayment, CancelFulfillments).
16
- - View (Presentation) - A presentation object which can render to multiple formats.
17
- - Repository (Data access) - Interacts with data sources to hide the implementation details to callers, and return Aggregates. Data sources could be an API, ActiveRecord, SQL, a local file, etc.
18
- - Aggregate (Domain/business Object) - Maps data from the data source to an object the aplication defines, known as an anti corruption layer.
13
+ - **Policy (Authorization)** - Can this user perform this process?
14
+ - **Operation (Services)** - Executes a single unit of business logic, or side effect (ScheduleAppointment, CancelOrder, UpdateAddress).
15
+ - **Workflow (Service Orchestration)** - Excecutes multiple units of work, and side effects (ApproveLoan, TakePayment, CancelFulfillments).
16
+ - **View (Presentation)** - A presentation object which can render to multiple formats.
17
+ - **Repository (Data access)** - Interacts with data sources to hide the implementation details to callers, and return Aggregates. Data sources could be an API, ActiveRecord, SQL, a local file, etc.
18
+ - **Aggregate (Domain/business Object)** - Maps data from the data source to an object the aplication defines, known as an anti corruption layer.
19
19
 
20
20
  Below is an example using NucleusCore Core with Rails:
21
21
 
@@ -0,0 +1,88 @@
1
+ # Rack::Utils patch for status code
2
+ class Utils
3
+ HTTP_STATUS_CODES = {
4
+ 100 => "Continue",
5
+ 101 => "Switching Protocols",
6
+ 102 => "Processing",
7
+ 103 => "Early Hints",
8
+ 200 => "OK",
9
+ 201 => "Created",
10
+ 202 => "Accepted",
11
+ 203 => "Non-Authoritative Information",
12
+ 204 => "No Content",
13
+ 205 => "Reset Content",
14
+ 206 => "Partial Content",
15
+ 207 => "Multi-Status",
16
+ 208 => "Already Reported",
17
+ 226 => "IM Used",
18
+ 300 => "Multiple Choices",
19
+ 301 => "Moved Permanently",
20
+ 302 => "Found",
21
+ 303 => "See Other",
22
+ 304 => "Not Modified",
23
+ 305 => "Use Proxy",
24
+ 306 => "(Unused)",
25
+ 307 => "Temporary Redirect",
26
+ 308 => "Permanent Redirect",
27
+ 400 => "Bad Request",
28
+ 401 => "Unauthorized",
29
+ 402 => "Payment Required",
30
+ 403 => "Forbidden",
31
+ 404 => "Not Found",
32
+ 405 => "Method Not Allowed",
33
+ 406 => "Not Acceptable",
34
+ 407 => "Proxy Authentication Required",
35
+ 408 => "Request Timeout",
36
+ 409 => "Conflict",
37
+ 410 => "Gone",
38
+ 411 => "Length Required",
39
+ 412 => "Precondition Failed",
40
+ 413 => "Payload Too Large",
41
+ 414 => "URI Too Long",
42
+ 415 => "Unsupported Media Type",
43
+ 416 => "Range Not Satisfiable",
44
+ 417 => "Expectation Failed",
45
+ 421 => "Misdirected Request",
46
+ 422 => "Unprocessable Entity",
47
+ 423 => "Locked",
48
+ 424 => "Failed Dependency",
49
+ 425 => "Too Early",
50
+ 426 => "Upgrade Required",
51
+ 428 => "Precondition Required",
52
+ 429 => "Too Many Requests",
53
+ 431 => "Request Header Fields Too Large",
54
+ 451 => "Unavailable for Legal Reasons",
55
+ 500 => "Internal Server Error",
56
+ 501 => "Not Implemented",
57
+ 502 => "Bad Gateway",
58
+ 503 => "Service Unavailable",
59
+ 504 => "Gateway Timeout",
60
+ 505 => "HTTP Version Not Supported",
61
+ 506 => "Variant Also Negotiates",
62
+ 507 => "Insufficient Storage",
63
+ 508 => "Loop Detected",
64
+ 509 => "Bandwidth Limit Exceeded",
65
+ 510 => "Not Extended",
66
+ 511 => "Network Authentication Required"
67
+ }.freeze
68
+
69
+ SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map do |code, message|
70
+ [message.downcase.gsub(/\s|-|'/, "_").to_sym, code]
71
+ end.flatten]
72
+
73
+ def self.status_code(status)
74
+ if status.is_a?(Symbol)
75
+ return SYMBOL_TO_STATUS_CODE.fetch(status) do
76
+ raise ArgumentError, "Unrecognized status code #{status.inspect}"
77
+ end
78
+ end
79
+
80
+ status.to_i
81
+ end
82
+
83
+ def self.wrap(object)
84
+ return [] if object.nil?
85
+
86
+ object.is_a?(Array) ? object : [object]
87
+ end
88
+ end
@@ -11,7 +11,7 @@ module NucleusCore
11
11
  policy_methods.each do |policy_method_and_args|
12
12
  next if send(*policy_method_and_args)
13
13
 
14
- name = Array.wrap(policy_method_and_args).first
14
+ name = Utils.wrap(policy_method_and_args).first
15
15
  message = "You do not have access to: #{name}"
16
16
 
17
17
  raise NucleusCore::NotAuthorized, message
@@ -10,12 +10,12 @@ module NucleusCore
10
10
  end
11
11
 
12
12
  def set_request_format(request=nil)
13
- @request_format = request&.to_sym || :json
13
+ @request_format = request&.to_sym || NucleusCore.configuration.default_response_format
14
14
  end
15
15
 
16
16
  # rubocop:disable Naming/AccessorMethodName
17
17
  def set_response_adapter(response_adapter)
18
- @response_adapter = response_adapter
18
+ @response_adapter = response_adapter || NucleusCore.configuration.response_adapter
19
19
  end
20
20
  # rubocop:enable Naming/AccessorMethodName
21
21
 
@@ -101,18 +101,16 @@ module NucleusCore
101
101
 
102
102
  # rubocop:disable Lint/DuplicateBranch
103
103
  def exception_to_status(exception)
104
- config = exception_map
105
-
106
104
  case exception
107
- when NucleusCore::NotFound, *config.not_found
105
+ when NucleusCore::NotFound, *exceptions.not_found
108
106
  :not_found
109
- when NucleusCore::BadRequest, *config.bad_request
107
+ when NucleusCore::BadRequest, *exceptions.bad_request
110
108
  :bad_request
111
- when NucleusCore::NotAuthorized, *config.forbidden
109
+ when NucleusCore::NotAuthorized, *exceptions.forbidden
112
110
  :forbidden
113
- when NucleusCore::Unprocessable, *config.unprocessable
111
+ when NucleusCore::Unprocessable, *exceptions.unprocessable
114
112
  :unprocessable_entity
115
- when NucleusCore::BaseException, *config.server_error
113
+ when NucleusCore::BaseException, *exceptions.server_error
116
114
  :internal_server_error
117
115
  else
118
116
  :internal_server_error
@@ -125,11 +123,11 @@ module NucleusCore
125
123
  end
126
124
 
127
125
  def logger(object, log_level=:info)
128
- NucleusCore.configuration.logger&.send(log_level, object)
126
+ NucleusCore.configuration&.logger&.send(log_level, object)
129
127
  end
130
128
 
131
- def exception_map
132
- NucleusCore.configuration.exceptions_map
129
+ def exceptions
130
+ NucleusCore.configuration.exceptions
133
131
  end
134
132
  end
135
133
  end
@@ -17,7 +17,7 @@ class NucleusCore::ResponseAdapter < NucleusCore::BasicObject
17
17
  end
18
18
 
19
19
  def status_code(status=nil)
20
- status = NucleusCore::Rack::Utils.status_code(status)
20
+ status = Utils.status_code(status)
21
21
  default_status = 200
22
22
 
23
23
  status.zero? ? default_status : status
@@ -1,3 +1,3 @@
1
1
  module NucleusCore
2
- VERSION = "0.1.4".freeze
2
+ VERSION = "0.1.5".freeze
3
3
  end
data/lib/nucleus_core.rb CHANGED
@@ -24,8 +24,8 @@ module NucleusCore
24
24
  class BadRequest < BaseException; end
25
25
 
26
26
  class Configuration
27
- attr_reader :exceptions_map
28
- attr_accessor :logger
27
+ attr_accessor :response_adapter, :default_response_format, :logger
28
+ attr_reader :exceptions
29
29
 
30
30
  RESPONSE_ADAPTER_METHODS = %i[
31
31
  render_json render_xml render_text render_pdf render_csv render_nothing set_header
@@ -33,11 +33,12 @@ module NucleusCore
33
33
 
34
34
  def initialize
35
35
  @logger = nil
36
- @exceptions_map = nil
36
+ @exceptions = format_exceptions
37
+ @default_response_format = :json
37
38
  end
38
39
 
39
- def exceptions_map=(args={})
40
- @exceptions_map = format_exceptions(args)
40
+ def exceptions=(args={})
41
+ @exceptions = format_exceptions(args)
41
42
  end
42
43
 
43
44
  private
@@ -50,13 +51,13 @@ module NucleusCore
50
51
 
51
52
  def format_exceptions(exceptions={})
52
53
  exception_defaults = ERROR_STATUSES.reduce({}) { |acc, ex| acc.merge(ex => nil) }
53
- exceptions_map = (exceptions || exception_defaults)
54
+ exceptions = (exceptions || exception_defaults)
54
55
  .slice(*exception_defaults.keys)
55
56
  .reduce({}) do |acc, (key, value)|
56
- acc.merge(key => Array.wrap(value))
57
+ acc.merge(key => Utils.wrap(value))
57
58
  end
58
59
 
59
- objectify(exceptions_map)
60
+ objectify(exceptions)
60
61
  end
61
62
  end
62
63
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nucleus-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - dodgerogers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-02 00:00:00.000000000 Z
11
+ date: 2023-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -151,8 +151,7 @@ files:
151
151
  - lib/nucleus_core/aggregate.rb
152
152
  - lib/nucleus_core/basic_object.rb
153
153
  - lib/nucleus_core/cli.rb
154
- - lib/nucleus_core/extensions/array.rb
155
- - lib/nucleus_core/extensions/rack.rb
154
+ - lib/nucleus_core/extensions/utils.rb
156
155
  - lib/nucleus_core/operation.rb
157
156
  - lib/nucleus_core/policy.rb
158
157
  - lib/nucleus_core/repository.rb
@@ -1,11 +0,0 @@
1
- class Array
2
- def self.wrap(object)
3
- if object.nil?
4
- []
5
- elsif object.respond_to?(:to_ary)
6
- object.to_ary || [object]
7
- else
8
- [object]
9
- end
10
- end
11
- end
@@ -1,86 +0,0 @@
1
- # Rack::Utils patch for status code
2
- module NucleusCore
3
- module Rack
4
- class Utils
5
- HTTP_STATUS_CODES = {
6
- 100 => "Continue",
7
- 101 => "Switching Protocols",
8
- 102 => "Processing",
9
- 103 => "Early Hints",
10
- 200 => "OK",
11
- 201 => "Created",
12
- 202 => "Accepted",
13
- 203 => "Non-Authoritative Information",
14
- 204 => "No Content",
15
- 205 => "Reset Content",
16
- 206 => "Partial Content",
17
- 207 => "Multi-Status",
18
- 208 => "Already Reported",
19
- 226 => "IM Used",
20
- 300 => "Multiple Choices",
21
- 301 => "Moved Permanently",
22
- 302 => "Found",
23
- 303 => "See Other",
24
- 304 => "Not Modified",
25
- 305 => "Use Proxy",
26
- 306 => "(Unused)",
27
- 307 => "Temporary Redirect",
28
- 308 => "Permanent Redirect",
29
- 400 => "Bad Request",
30
- 401 => "Unauthorized",
31
- 402 => "Payment Required",
32
- 403 => "Forbidden",
33
- 404 => "Not Found",
34
- 405 => "Method Not Allowed",
35
- 406 => "Not Acceptable",
36
- 407 => "Proxy Authentication Required",
37
- 408 => "Request Timeout",
38
- 409 => "Conflict",
39
- 410 => "Gone",
40
- 411 => "Length Required",
41
- 412 => "Precondition Failed",
42
- 413 => "Payload Too Large",
43
- 414 => "URI Too Long",
44
- 415 => "Unsupported Media Type",
45
- 416 => "Range Not Satisfiable",
46
- 417 => "Expectation Failed",
47
- 421 => "Misdirected Request",
48
- 422 => "Unprocessable Entity",
49
- 423 => "Locked",
50
- 424 => "Failed Dependency",
51
- 425 => "Too Early",
52
- 426 => "Upgrade Required",
53
- 428 => "Precondition Required",
54
- 429 => "Too Many Requests",
55
- 431 => "Request Header Fields Too Large",
56
- 451 => "Unavailable for Legal Reasons",
57
- 500 => "Internal Server Error",
58
- 501 => "Not Implemented",
59
- 502 => "Bad Gateway",
60
- 503 => "Service Unavailable",
61
- 504 => "Gateway Timeout",
62
- 505 => "HTTP Version Not Supported",
63
- 506 => "Variant Also Negotiates",
64
- 507 => "Insufficient Storage",
65
- 508 => "Loop Detected",
66
- 509 => "Bandwidth Limit Exceeded",
67
- 510 => "Not Extended",
68
- 511 => "Network Authentication Required"
69
- }.freeze
70
-
71
- SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map do |code, message|
72
- [message.downcase.gsub(/\s|-|'/, "_").to_sym, code]
73
- end.flatten]
74
-
75
- def self.status_code(status)
76
- if status.is_a?(Symbol)
77
- return SYMBOL_TO_STATUS_CODE.fetch(status) do
78
- raise ArgumentError, "Unrecognized status code #{status.inspect}"
79
- end
80
- end
81
-
82
- status.to_i
83
- end
84
- end
85
- end
86
- end