treaty 0.19.0 → 0.20.0

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/treaty/action/base.rb +11 -0
  4. data/lib/treaty/action/context/callable.rb +90 -0
  5. data/lib/treaty/action/context/dsl.rb +56 -0
  6. data/lib/treaty/action/context/workspace.rb +92 -0
  7. data/lib/treaty/action/executor/inventory.rb +136 -0
  8. data/lib/treaty/{info/rest → action/info}/builder.rb +2 -2
  9. data/lib/treaty/{info/rest → action/info}/dsl.rb +2 -2
  10. data/lib/treaty/{info/rest → action/info}/result.rb +2 -2
  11. data/lib/treaty/action/inventory/collection.rb +77 -0
  12. data/lib/treaty/action/inventory/factory.rb +108 -0
  13. data/lib/treaty/action/inventory/inventory.rb +146 -0
  14. data/lib/treaty/action/request/attribute/attribute.rb +76 -0
  15. data/lib/treaty/action/request/attribute/builder.rb +98 -0
  16. data/lib/treaty/action/request/entity.rb +78 -0
  17. data/lib/treaty/action/request/factory.rb +116 -0
  18. data/lib/treaty/action/request/validator.rb +120 -0
  19. data/lib/treaty/action/response/attribute/attribute.rb +79 -0
  20. data/lib/treaty/action/response/attribute/builder.rb +96 -0
  21. data/lib/treaty/action/response/entity.rb +79 -0
  22. data/lib/treaty/action/response/factory.rb +129 -0
  23. data/lib/treaty/action/response/validator.rb +111 -0
  24. data/lib/treaty/action/result.rb +81 -0
  25. data/lib/treaty/action/versions/collection.rb +47 -0
  26. data/lib/treaty/action/versions/dsl.rb +116 -0
  27. data/lib/treaty/action/versions/execution/request.rb +287 -0
  28. data/lib/treaty/action/versions/executor.rb +61 -0
  29. data/lib/treaty/action/versions/factory.rb +253 -0
  30. data/lib/treaty/action/versions/resolver.rb +150 -0
  31. data/lib/treaty/action/versions/semantic.rb +64 -0
  32. data/lib/treaty/action/versions/workspace.rb +106 -0
  33. data/lib/treaty/action.rb +31 -0
  34. data/lib/treaty/controller/dsl.rb +1 -1
  35. data/lib/treaty/entity/attribute/base.rb +1 -1
  36. data/lib/treaty/entity/attribute/builder/base.rb +1 -1
  37. data/lib/treaty/entity/attribute/dsl.rb +1 -1
  38. data/lib/treaty/entity/base.rb +1 -1
  39. data/lib/treaty/entity/builder.rb +62 -5
  40. data/lib/treaty/version.rb +1 -1
  41. metadata +32 -31
  42. data/lib/treaty/base.rb +0 -9
  43. data/lib/treaty/context/callable.rb +0 -26
  44. data/lib/treaty/context/dsl.rb +0 -12
  45. data/lib/treaty/context/workspace.rb +0 -32
  46. data/lib/treaty/executor/inventory.rb +0 -122
  47. data/lib/treaty/inventory/collection.rb +0 -71
  48. data/lib/treaty/inventory/factory.rb +0 -91
  49. data/lib/treaty/inventory/inventory.rb +0 -92
  50. data/lib/treaty/request/attribute/attribute.rb +0 -25
  51. data/lib/treaty/request/attribute/builder.rb +0 -46
  52. data/lib/treaty/request/entity.rb +0 -33
  53. data/lib/treaty/request/factory.rb +0 -81
  54. data/lib/treaty/request/validator.rb +0 -60
  55. data/lib/treaty/response/attribute/attribute.rb +0 -25
  56. data/lib/treaty/response/attribute/builder.rb +0 -46
  57. data/lib/treaty/response/entity.rb +0 -33
  58. data/lib/treaty/response/factory.rb +0 -87
  59. data/lib/treaty/response/validator.rb +0 -53
  60. data/lib/treaty/result.rb +0 -23
  61. data/lib/treaty/versions/collection.rb +0 -15
  62. data/lib/treaty/versions/dsl.rb +0 -42
  63. data/lib/treaty/versions/execution/request.rb +0 -177
  64. data/lib/treaty/versions/executor.rb +0 -14
  65. data/lib/treaty/versions/factory.rb +0 -112
  66. data/lib/treaty/versions/resolver.rb +0 -70
  67. data/lib/treaty/versions/semantic.rb +0 -22
  68. data/lib/treaty/versions/workspace.rb +0 -43
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Request
5
- module Attribute
6
- # Request-specific attribute builder
7
- class Builder < Treaty::Entity::Attribute::Builder::Base
8
- private
9
-
10
- def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
11
- Attribute.new(
12
- name,
13
- type,
14
- *helpers,
15
- nesting_level:,
16
- **options,
17
- &block
18
- )
19
- end
20
-
21
- # Deep copies an attribute with adjusted nesting level for Request context.
22
- #
23
- # @param source_attribute [Treaty::Entity::Attribute::Base] Attribute to copy
24
- # @param new_nesting_level [Integer] New nesting level
25
- # @return [Request::Attribute::Attribute] Copied attribute
26
- def deep_copy_attribute(source_attribute, new_nesting_level) # rubocop:disable Metrics/MethodLength
27
- copied = Attribute.new(
28
- source_attribute.name,
29
- source_attribute.type,
30
- nesting_level: new_nesting_level,
31
- **deep_copy_options(source_attribute.options)
32
- )
33
-
34
- return copied unless source_attribute.nested?
35
-
36
- source_attribute.collection_of_attributes.each do |nested_source|
37
- nested_copied = deep_copy_attribute(nested_source, new_nesting_level + 1)
38
- copied.collection_of_attributes << nested_copied
39
- end
40
-
41
- copied
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Request
5
- # Entity class for request definitions.
6
- # Attributes are required by default.
7
- #
8
- # This class is used internally when defining request blocks.
9
- # When you write a request block, Treaty creates an anonymous
10
- # class based on Request::Entity.
11
- class Entity
12
- include Treaty::Entity::Attribute::DSL
13
-
14
- class << self
15
- private
16
-
17
- # Creates a Request::Attribute::Attribute for this Request::Entity class
18
- #
19
- # @return [Request::Attribute::Attribute] Created attribute instance
20
- def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
21
- Attribute::Attribute.new(
22
- name,
23
- type,
24
- *helpers,
25
- nesting_level:,
26
- **options,
27
- &block
28
- )
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Request
5
- # Factory for creating request definitions.
6
- #
7
- # Supports two modes:
8
- # 1. Block mode: Creates an anonymous Request::Entity class with the block
9
- # 2. Entity mode: Uses a provided Entity class directly
10
- #
11
- # ## Block Mode
12
- #
13
- # ```ruby
14
- # request do
15
- # object :post do
16
- # string :title
17
- # end
18
- # end
19
- # ```
20
- #
21
- # ## Entity Mode
22
- #
23
- # ```ruby
24
- # request Posts::Create::RequestEntity
25
- # ```
26
- class Factory
27
- # Uses a provided Entity class
28
- #
29
- # @param entity_class [Class] Entity class to use
30
- # @return [void]
31
- # @raise [Treaty::Exceptions::Validation] if entity_class is not a valid Treaty::Entity::Base subclass
32
- def use_entity(entity_class)
33
- validate_entity_class!(entity_class)
34
- @entity_class = entity_class
35
- end
36
-
37
- # Returns collection of attributes from the entity class
38
- #
39
- # @return [Collection] Collection of attributes
40
- def collection_of_attributes
41
- return Treaty::Entity::Attribute::Collection.new if @entity_class.nil?
42
-
43
- @entity_class.collection_of_attributes
44
- end
45
-
46
- # Handles DSL methods for defining attributes
47
- #
48
- # This allows the factory to be used with method_missing
49
- # for backwards compatibility with direct method calls.
50
- # Creates an anonymous Request::Entity class on first use.
51
- def method_missing(type, *helpers, **options, &block)
52
- # If no entity class yet, create one
53
- @entity_class ||= Class.new(Entity)
54
-
55
- # Call the method on the entity class
56
- @entity_class.public_send(type, *helpers, **options, &block)
57
- end
58
-
59
- def respond_to_missing?(name, *)
60
- super
61
- end
62
-
63
- private
64
-
65
- # Validates that the provided entity_class is a valid Treaty::Entity::Base subclass
66
- #
67
- # @param entity_class [Class] Entity class to validate
68
- # @raise [Treaty::Exceptions::Validation] if entity_class is not a valid Treaty::Entity::Base subclass
69
- def validate_entity_class!(entity_class)
70
- return if entity_class.is_a?(Class) && entity_class < Treaty::Entity::Base
71
-
72
- raise Treaty::Exceptions::Validation,
73
- I18n.t(
74
- "treaty.request.factory.invalid_entity_class",
75
- type: entity_class.class,
76
- value: entity_class
77
- )
78
- end
79
- end
80
- end
81
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Request
5
- # Validator for request data
6
- class Validator
7
- class << self
8
- # Validates request parameters against the request definition
9
- #
10
- # @param params [Hash] Request parameters to validate
11
- # @param version_factory [Versions::Factory] Version factory with request definition
12
- # @return [Hash] Validated and transformed parameters
13
- def validate!(params:, version_factory:)
14
- new(params:, version_factory:).validate!
15
- end
16
- end
17
-
18
- def initialize(params:, version_factory:)
19
- @params = params
20
- @version_factory = version_factory
21
- end
22
-
23
- def validate!
24
- validate_request_attributes!
25
- end
26
-
27
- private
28
-
29
- def request_data
30
- @request_data ||= begin
31
- @params.to_unsafe_h
32
- rescue NoMethodError
33
- @params
34
- end
35
- end
36
-
37
- def validate_request_attributes!
38
- return request_data unless request_attributes_exist?
39
-
40
- # Validate request attributes with orchestrator:
41
- orchestrator_class = Class.new(Treaty::Entity::Attribute::Validation::Orchestrator::Base) do
42
- define_method(:collection_of_attributes) do
43
- @version_factory.request_factory.collection_of_attributes
44
- end
45
- end
46
-
47
- orchestrator_class.validate!(
48
- version_factory: @version_factory,
49
- data: request_data
50
- )
51
- end
52
-
53
- def request_attributes_exist?
54
- return false if @version_factory.request_factory&.collection_of_attributes&.empty?
55
-
56
- @version_factory.request_factory.collection_of_attributes.exists?
57
- end
58
- end
59
- end
60
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Response
5
- module Attribute
6
- # Response-specific attribute that defaults to required: false
7
- class Attribute < Treaty::Entity::Attribute::Base
8
- private
9
-
10
- def apply_defaults!
11
- # For response: optional by default (false).
12
- # message: nil means use I18n default message from validators
13
- @options[:required] ||= { is: false, message: nil }
14
- end
15
-
16
- def process_nested_attributes(&block)
17
- return unless object_or_array?
18
-
19
- builder = Builder.new(collection_of_attributes, @nesting_level + 1)
20
- builder.instance_eval(&block)
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Response
5
- module Attribute
6
- # Response-specific attribute builder
7
- class Builder < Treaty::Entity::Attribute::Builder::Base
8
- private
9
-
10
- def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
11
- Attribute.new(
12
- name,
13
- type,
14
- *helpers,
15
- nesting_level:,
16
- **options,
17
- &block
18
- )
19
- end
20
-
21
- # Deep copies an attribute with adjusted nesting level for Response context.
22
- #
23
- # @param source_attribute [Treaty::Entity::Attribute::Base] Attribute to copy
24
- # @param new_nesting_level [Integer] New nesting level
25
- # @return [Response::Attribute::Attribute] Copied attribute
26
- def deep_copy_attribute(source_attribute, new_nesting_level) # rubocop:disable Metrics/MethodLength
27
- copied = Attribute.new(
28
- source_attribute.name,
29
- source_attribute.type,
30
- nesting_level: new_nesting_level,
31
- **deep_copy_options(source_attribute.options)
32
- )
33
-
34
- return copied unless source_attribute.nested?
35
-
36
- source_attribute.collection_of_attributes.each do |nested_source|
37
- nested_copied = deep_copy_attribute(nested_source, new_nesting_level + 1)
38
- copied.collection_of_attributes << nested_copied
39
- end
40
-
41
- copied
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Response
5
- # Entity class for response definitions.
6
- # Attributes are optional by default.
7
- #
8
- # This class is used internally when defining response blocks.
9
- # When you write a response block, Treaty creates an anonymous
10
- # class based on Response::Entity.
11
- class Entity
12
- include Treaty::Entity::Attribute::DSL
13
-
14
- class << self
15
- private
16
-
17
- # Creates a Response::Attribute::Attribute for this Response::Entity class
18
- #
19
- # @return [Response::Attribute::Attribute] Created attribute instance
20
- def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
21
- Attribute::Attribute.new(
22
- name,
23
- type,
24
- *helpers,
25
- nesting_level:,
26
- **options,
27
- &block
28
- )
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Response
5
- # Factory for creating response definitions.
6
- #
7
- # Supports two modes:
8
- # 1. Block mode: Creates an anonymous Response::Entity class with the block
9
- # 2. Entity mode: Uses a provided Entity class directly
10
- #
11
- # ## Block Mode
12
- #
13
- # ```ruby
14
- # response 200 do
15
- # object :post do
16
- # string :id
17
- # end
18
- # end
19
- # ```
20
- #
21
- # ## Entity Mode
22
- #
23
- # ```ruby
24
- # response 200, Posts::Create::ResponseEntity
25
- # ```
26
- class Factory
27
- attr_reader :status
28
-
29
- def initialize(status)
30
- @status = status
31
- end
32
-
33
- # Uses a provided Entity class
34
- #
35
- # @param entity_class [Class] Entity class to use
36
- # @return [void]
37
- # @raise [Treaty::Exceptions::Validation] if entity_class is not a valid Treaty::Entity::Base subclass
38
- def use_entity(entity_class)
39
- validate_entity_class!(entity_class)
40
- @entity_class = entity_class
41
- end
42
-
43
- # Returns collection of attributes from the entity class
44
- #
45
- # @return [Collection] Collection of attributes
46
- def collection_of_attributes
47
- return Treaty::Entity::Attribute::Collection.new if @entity_class.nil?
48
-
49
- @entity_class.collection_of_attributes
50
- end
51
-
52
- # Handles DSL methods for defining attributes
53
- #
54
- # This allows the factory to be used with method_missing
55
- # for backwards compatibility with direct method calls.
56
- # Creates an anonymous Response::Entity class on first use.
57
- def method_missing(type, *helpers, **options, &block)
58
- # If no entity class yet, create one
59
- @entity_class ||= Class.new(Entity)
60
-
61
- # Call the method on the entity class
62
- @entity_class.public_send(type, *helpers, **options, &block)
63
- end
64
-
65
- def respond_to_missing?(name, *)
66
- super
67
- end
68
-
69
- private
70
-
71
- # Validates that the provided entity_class is a valid Treaty::Entity::Base subclass
72
- #
73
- # @param entity_class [Class] Entity class to validate
74
- # @raise [Treaty::Exceptions::Validation] if entity_class is not a valid Treaty::Entity::Base subclass
75
- def validate_entity_class!(entity_class)
76
- return if entity_class.is_a?(Class) && entity_class < Treaty::Entity::Base
77
-
78
- raise Treaty::Exceptions::Validation,
79
- I18n.t(
80
- "treaty.response.factory.invalid_entity_class",
81
- type: entity_class.class,
82
- value: entity_class
83
- )
84
- end
85
- end
86
- end
87
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Response
5
- # Validator for response data
6
- class Validator
7
- class << self
8
- # Validates response data against the response definition
9
- #
10
- # @param response_data [Hash] Response data to validate
11
- # @param version_factory [Versions::Factory] Version factory with response definition
12
- # @return [Hash] Validated and transformed response data
13
- def validate!(version_factory:, response_data: {})
14
- new(version_factory:, response_data:).validate!
15
- end
16
- end
17
-
18
- def initialize(version_factory:, response_data: {})
19
- @version_factory = version_factory
20
- @response_data = response_data
21
- end
22
-
23
- def validate!
24
- validate_response_attributes!
25
- end
26
-
27
- private
28
-
29
- def validate_response_attributes!
30
- return @response_data unless response_attributes_exist?
31
-
32
- # Create orchestrator for response validation
33
- # Orchestrator filters data by attributes and performs transformation
34
- orchestrator_class = Class.new(Treaty::Entity::Attribute::Validation::Orchestrator::Base) do
35
- define_method(:collection_of_attributes) do
36
- @version_factory.response_factory.collection_of_attributes
37
- end
38
- end
39
-
40
- orchestrator_class.validate!(
41
- version_factory: @version_factory,
42
- data: @response_data
43
- )
44
- end
45
-
46
- def response_attributes_exist?
47
- return false if @version_factory.response_factory&.collection_of_attributes&.empty?
48
-
49
- @version_factory.response_factory.collection_of_attributes.exists?
50
- end
51
- end
52
- end
53
- end
data/lib/treaty/result.rb DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- class Result
5
- attr_reader :data, :status, :version
6
-
7
- def initialize(data:, status:, version:)
8
- @data = data
9
- @status = status
10
- @version = version
11
- end
12
-
13
- def inspect
14
- "#<#{self.class.name} #{draw_result}>"
15
- end
16
-
17
- private
18
-
19
- def draw_result
20
- "@data=#{@data.inspect}, @status=#{@status.inspect}, @version=#{@version.inspect}"
21
- end
22
- end
23
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Versions
5
- class Collection
6
- extend Forwardable
7
-
8
- def_delegators :@collection, :<<, :map, :find
9
-
10
- def initialize(collection = Set.new)
11
- @collection = collection
12
- end
13
- end
14
- end
15
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Treaty
4
- module Versions
5
- module DSL
6
- def self.included(base)
7
- base.extend(ClassMethods)
8
- base.include(Workspace)
9
- end
10
-
11
- module ClassMethods
12
- private
13
-
14
- def version(version, default: false, &block)
15
- @version_factory = Factory.new(version:, default:)
16
-
17
- @version_factory.instance_eval(&block)
18
- @version_factory.validate_after_block!
19
-
20
- validate_multiple_defaults! if @version_factory.default_result == true
21
-
22
- collection_of_versions << @version_factory
23
-
24
- @version_factory = nil
25
- end
26
-
27
- def collection_of_versions
28
- @collection_of_versions ||= Collection.new
29
- end
30
-
31
- def validate_multiple_defaults!
32
- existing_defaults = collection_of_versions.map(&:default_result).count(true)
33
-
34
- return if existing_defaults.zero?
35
-
36
- raise Treaty::Exceptions::VersionMultipleDefaults,
37
- I18n.t("treaty.versioning.factory.multiple_defaults")
38
- end
39
- end
40
- end
41
- end
42
- end