thunderoperation 0.2.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.
- checksums.yaml +7 -0
- data/README.md +3 -0
- data/config/default.yml +11 -0
- data/lib/rubocop/cop/thunderoperation/call_handlers.rb +56 -0
- data/lib/rubocop/cop/thunderoperation/def_outside_steps.rb +39 -0
- data/lib/rubocop/cop/thunderoperation/flow_required.rb +24 -0
- data/lib/rubocop/cop/thunderoperation/missing_steps.rb +42 -0
- data/lib/rubocop/cop/thunderoperation/operation_helpers.rb +124 -0
- data/lib/rubocop/cop/thunderoperation/operation_section_order.rb +51 -0
- data/lib/rubocop/cop/thunderoperation/steps_cannot_call_steps.rb +36 -0
- data/lib/rubocop/cop/thunderoperation/steps_order.rb +52 -0
- data/lib/rubocop/cop/thunderoperation/unknown_step.rb +61 -0
- data/lib/rubocop/cop/thunderoperation/unused_step.rb +29 -0
- data/lib/thunderoperation/adapter.rb +23 -0
- data/lib/thunderoperation/adapters/framer.rb +64 -0
- data/lib/thunderoperation/adapters/interruptable.rb +19 -0
- data/lib/thunderoperation/adapters/rich_parameters.rb +42 -0
- data/lib/thunderoperation/adapters/validations.rb +49 -0
- data/lib/thunderoperation/base.rb +144 -0
- data/lib/thunderoperation/clauses/base.rb +11 -0
- data/lib/thunderoperation/clauses/transaction.rb +11 -0
- data/lib/thunderoperation/clauses.rb +11 -0
- data/lib/thunderoperation/concerns/has_adapter.rb +47 -0
- data/lib/thunderoperation/config.rb +30 -0
- data/lib/thunderoperation/exceptions/trail.rb +27 -0
- data/lib/thunderoperation/exceptions.rb +32 -0
- data/lib/thunderoperation/flow/builder.rb +31 -0
- data/lib/thunderoperation/flow.rb +57 -0
- data/lib/thunderoperation/handlers.rb +43 -0
- data/lib/thunderoperation/lookup.rb +13 -0
- data/lib/thunderoperation/parameters/array_parameter.rb +48 -0
- data/lib/thunderoperation/parameters/base.rb +92 -0
- data/lib/thunderoperation/parameters/hash_parameter.rb +154 -0
- data/lib/thunderoperation/parameters.rb +11 -0
- data/lib/thunderoperation/response.rb +62 -0
- data/lib/thunderoperation/rubocop.rb +31 -0
- data/lib/thunderoperation/steps/base.rb +44 -0
- data/lib/thunderoperation/steps/clause.rb +32 -0
- data/lib/thunderoperation/steps/method.rb +34 -0
- data/lib/thunderoperation/steps/render.rb +22 -0
- data/lib/thunderoperation/steps/success.rb +29 -0
- data/lib/thunderoperation/steps.rb +33 -0
- data/lib/thunderoperation/steps_definition.rb +75 -0
- data/lib/thunderoperation/version.rb +5 -0
- data/lib/thunderoperation.rb +36 -0
- metadata +108 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Parameters
|
|
5
|
+
class HashParameter < Base
|
|
6
|
+
attr_reader :configuration
|
|
7
|
+
|
|
8
|
+
def initialize(_type = nil, options = {}, &block)
|
|
9
|
+
super(Hash, options)
|
|
10
|
+
|
|
11
|
+
@configuration = {}
|
|
12
|
+
|
|
13
|
+
instance_exec(&block) if block
|
|
14
|
+
check_map_declaration!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def param(field_name, *, &)
|
|
18
|
+
@configuration[field_name.to_sym] = self.class.from_args(*, &)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# WARN: AI MADE
|
|
22
|
+
# The word of returns and event payloads (`returns Hash do field :title, String end`); params keep `param`.
|
|
23
|
+
alias field param
|
|
24
|
+
|
|
25
|
+
# A nested Hash read from an object's association when an external operation renders its result; elsewhere,
|
|
26
|
+
# the same as `field name, Hash do ... end`.
|
|
27
|
+
def association(field_name, options = {}, &)
|
|
28
|
+
field(field_name, Hash, options, &)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# WARN: AI MADE
|
|
32
|
+
# A map: `keys Date` and `values Integer` (or `values Hash do ... end`), for a Hash whose keys are data (dates,
|
|
33
|
+
# ids); a Hash with fixed keys declares them with `field`. A protobuf `map`.
|
|
34
|
+
def keys(*args)
|
|
35
|
+
return @keys if args.empty?
|
|
36
|
+
|
|
37
|
+
@keys = Base.from_args(*args)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def values(*args, &)
|
|
41
|
+
return @values if args.empty? && !block_given?
|
|
42
|
+
|
|
43
|
+
@values = Base.from_args(*args, &)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def map? = !@keys.nil? || !@values.nil?
|
|
47
|
+
|
|
48
|
+
def output_keys
|
|
49
|
+
@configuration.map { |field_name, parameter| parameter.options[:as] || field_name }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def filter(value)
|
|
53
|
+
return FILTERED if sensitive?
|
|
54
|
+
return value if value.nil?
|
|
55
|
+
return value.transform_values { |item| @values.filter(item) } if map?
|
|
56
|
+
return value if @configuration.empty?
|
|
57
|
+
|
|
58
|
+
filter_fields(value)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def sanitize(value, path: nil)
|
|
62
|
+
validate!(value, path:)
|
|
63
|
+
|
|
64
|
+
return if value.nil?
|
|
65
|
+
return sanitize_map(value, path) if map?
|
|
66
|
+
return value if @configuration.empty?
|
|
67
|
+
|
|
68
|
+
@configuration.filter_map { |field_name, parameter| sanitize_field(value, field_name, parameter, path) }.to_h
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# WARN: AI MADE
|
|
72
|
+
def resolve_types!(&)
|
|
73
|
+
@configuration.each_value { |parameter| parameter.resolve_types!(&) }
|
|
74
|
+
@keys&.resolve_types!(&)
|
|
75
|
+
@values&.resolve_types!(&)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def check!(value, path: nil)
|
|
79
|
+
validate!(value, path:)
|
|
80
|
+
return if value.nil?
|
|
81
|
+
return check_map!(value, path) if map?
|
|
82
|
+
return if @configuration.empty?
|
|
83
|
+
|
|
84
|
+
unknown = value.keys.map(&:to_sym) - @configuration.keys
|
|
85
|
+
if unknown.any?
|
|
86
|
+
field_path = [path, unknown.first].compact.join('.')
|
|
87
|
+
raise Exceptions::ParameterError.new("Unknown field '#{field_path}'", field: field_path)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
@configuration.each { |field_name, parameter| check_field!(value, field_name, parameter, path) }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
# WARN: AI MADE
|
|
96
|
+
def check_map_declaration!
|
|
97
|
+
return unless map?
|
|
98
|
+
raise Exceptions::DeclarationError, 'a map declares both keys and values' if @keys.nil? || @values.nil?
|
|
99
|
+
return if @configuration.empty?
|
|
100
|
+
|
|
101
|
+
raise Exceptions::DeclarationError, 'a Hash declares fields or keys/values, not both'
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def filter_fields(value)
|
|
105
|
+
@configuration.filter_map do |field_name, parameter|
|
|
106
|
+
key = parameter.options[:as] || field_name
|
|
107
|
+
[key, parameter.filter(value[key])] if value.key?(key)
|
|
108
|
+
end.to_h
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def check_map!(value, path)
|
|
112
|
+
value.each do |key, item|
|
|
113
|
+
@keys.check!(key, path: "#{path}[#{key}]")
|
|
114
|
+
@values.check!(item, path: "#{path}[#{key}]")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def sanitize_map(value, path)
|
|
119
|
+
value.to_h do |key, item|
|
|
120
|
+
[@keys.sanitize(key, path: "#{path}[#{key}]"), @values.sanitize(item, path: "#{path}[#{key}]")]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def check_field!(value, field_name, parameter, path)
|
|
125
|
+
key = input_key(value, field_name)
|
|
126
|
+
field_path = path ? "#{path}.#{field_name}" : field_name.to_s
|
|
127
|
+
|
|
128
|
+
if key
|
|
129
|
+
parameter.check!(value[key], path: field_path)
|
|
130
|
+
elsif parameter.required?
|
|
131
|
+
raise Exceptions::ParameterError.new("Required field '#{field_path}' is missing", field: field_path)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def sanitize_field(value, field_name, parameter, path)
|
|
136
|
+
key = input_key(value, field_name)
|
|
137
|
+
field_path = path ? "#{path}.#{field_name}" : field_name.to_s
|
|
138
|
+
|
|
139
|
+
if key
|
|
140
|
+
[parameter.options[:as] || field_name, parameter.sanitize(value[key], path: field_path)]
|
|
141
|
+
elsif parameter.required?
|
|
142
|
+
raise Exceptions::ParameterError.new("Required field '#{field_path}' is missing", field: field_path)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def input_key(value, field_name)
|
|
147
|
+
return field_name if value.key?(field_name)
|
|
148
|
+
|
|
149
|
+
string_key = field_name.name
|
|
150
|
+
string_key if value.key?(string_key)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
Response = Data.define(
|
|
5
|
+
:payload,
|
|
6
|
+
:was_success,
|
|
7
|
+
:error,
|
|
8
|
+
:status,
|
|
9
|
+
:headers,
|
|
10
|
+
:failed_step,
|
|
11
|
+
:operation_name
|
|
12
|
+
) do
|
|
13
|
+
def initialize(error: nil, status: nil, headers: nil, failed_step: nil, **args)
|
|
14
|
+
super(**args, error:, status:, headers:, failed_step:)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def success?
|
|
18
|
+
was_success
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def failure?
|
|
22
|
+
!was_success
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
alias_method :failed?, :failure?
|
|
26
|
+
|
|
27
|
+
def failure_message
|
|
28
|
+
error&.message
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def failure_extras
|
|
32
|
+
error.extras if error.respond_to?(:extras)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def trail
|
|
36
|
+
return [] unless error.respond_to?(:operation_trail)
|
|
37
|
+
|
|
38
|
+
error.operation_trail.map(&:to_s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def interrupted?
|
|
42
|
+
error.is_a?(Exceptions::Interruption)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def failure_data
|
|
46
|
+
return unless error
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
failed_step:,
|
|
50
|
+
trail:,
|
|
51
|
+
failure_message: error.message,
|
|
52
|
+
error_class: error.class.name,
|
|
53
|
+
operation_name:,
|
|
54
|
+
failure_extras:
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_h
|
|
59
|
+
super.merge(failure_data:)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Entry point for `require: thunderoperation/rubocop` in .rubocop.yml: cops for the operation DSL.
|
|
4
|
+
require 'rubocop'
|
|
5
|
+
|
|
6
|
+
# WARN: AI MADE
|
|
7
|
+
# The defaults in config/default.yml, merged into RuboCop's own, so a project only has to load the cops.
|
|
8
|
+
module ThunderOperation
|
|
9
|
+
module RuboCop
|
|
10
|
+
CONFIG_DEFAULT = File.expand_path('../../config/default.yml', __dir__)
|
|
11
|
+
|
|
12
|
+
def self.inject_defaults!
|
|
13
|
+
hash = ::RuboCop::ConfigLoader.send(:load_yaml_configuration, CONFIG_DEFAULT)
|
|
14
|
+
config = ::RuboCop::ConfigLoader.merge_with_default(::RuboCop::Config.new(hash, CONFIG_DEFAULT), CONFIG_DEFAULT)
|
|
15
|
+
::RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
ThunderOperation::RuboCop.inject_defaults!
|
|
21
|
+
|
|
22
|
+
require_relative '../rubocop/cop/thunderoperation/operation_helpers'
|
|
23
|
+
require_relative '../rubocop/cop/thunderoperation/operation_section_order'
|
|
24
|
+
require_relative '../rubocop/cop/thunderoperation/flow_required'
|
|
25
|
+
require_relative '../rubocop/cop/thunderoperation/unknown_step'
|
|
26
|
+
require_relative '../rubocop/cop/thunderoperation/missing_steps'
|
|
27
|
+
require_relative '../rubocop/cop/thunderoperation/unused_step'
|
|
28
|
+
require_relative '../rubocop/cop/thunderoperation/steps_order'
|
|
29
|
+
require_relative '../rubocop/cop/thunderoperation/steps_cannot_call_steps'
|
|
30
|
+
require_relative '../rubocop/cop/thunderoperation/def_outside_steps'
|
|
31
|
+
require_relative '../rubocop/cop/thunderoperation/call_handlers'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Steps
|
|
5
|
+
class Base
|
|
6
|
+
def self.build(_name, *args, **kwargs)
|
|
7
|
+
new(*args, **kwargs)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.step_name
|
|
11
|
+
@step_name ||= name.demodulize.underscore.to_sym
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
freeze
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def name
|
|
19
|
+
self.class.step_name
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run(_instance)
|
|
23
|
+
raise NotImplementedError, "#{self.class.name}#run"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_s
|
|
27
|
+
name.to_s
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def inspect
|
|
31
|
+
"#<#{self.class.name} #{self}>"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def signature(name, args, kwargs)
|
|
37
|
+
rendered = args.map(&:inspect) + kwargs.map { |key, value| "#{key}: #{value.inspect}" }
|
|
38
|
+
return name.to_s if rendered.empty?
|
|
39
|
+
|
|
40
|
+
"#{name}(#{rendered.join(', ')})"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Steps
|
|
5
|
+
class Clause < Base
|
|
6
|
+
attr_reader :name, :handler, :args, :kwargs, :flow
|
|
7
|
+
|
|
8
|
+
def initialize(name, handler, *args, **kwargs, &block)
|
|
9
|
+
raise ArgumentError, "clause `#{name}` requires a block" unless block
|
|
10
|
+
|
|
11
|
+
@name = name.to_sym
|
|
12
|
+
@handler = handler
|
|
13
|
+
@args = args.freeze
|
|
14
|
+
@kwargs = kwargs.freeze
|
|
15
|
+
@flow = Flow.build(&block)
|
|
16
|
+
super()
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def steps
|
|
20
|
+
flow.steps
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def run(instance)
|
|
24
|
+
handler.call(instance, *args, **kwargs) { flow.run(instance) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
"#{signature(name, args, kwargs)} { #{flow} }"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Steps
|
|
5
|
+
class Method < Base
|
|
6
|
+
attr_reader :name, :args, :kwargs
|
|
7
|
+
|
|
8
|
+
def self.build(name, *args, **kwargs)
|
|
9
|
+
new(name, *args, **kwargs)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(name, *args, **kwargs)
|
|
13
|
+
@name = name.to_sym
|
|
14
|
+
@args = args.freeze
|
|
15
|
+
@kwargs = kwargs.freeze
|
|
16
|
+
super()
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def run(instance)
|
|
20
|
+
if args.empty? && kwargs.empty?
|
|
21
|
+
instance.send(name)
|
|
22
|
+
else
|
|
23
|
+
instance.send(name, *args, **kwargs)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
signature(name, args, kwargs)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Steps
|
|
5
|
+
class Render < Success
|
|
6
|
+
attr_reader :status
|
|
7
|
+
|
|
8
|
+
def initialize(payload = nil, status: nil)
|
|
9
|
+
@status = status
|
|
10
|
+
super(payload)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(instance)
|
|
14
|
+
instance._success(resolve(instance), status:)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_s
|
|
18
|
+
signature(:render, payload.nil? ? [] : [payload], status ? { status: } : {})
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Steps
|
|
5
|
+
class Success < Base
|
|
6
|
+
attr_reader :payload
|
|
7
|
+
|
|
8
|
+
def initialize(payload = nil)
|
|
9
|
+
@payload = payload
|
|
10
|
+
@ivar = :"@#{payload}" if payload.is_a?(Symbol)
|
|
11
|
+
super()
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run(instance)
|
|
15
|
+
instance._success(resolve(instance))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_s
|
|
19
|
+
payload.nil? ? 'success' : "success(#{payload.inspect})"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
protected
|
|
23
|
+
|
|
24
|
+
def resolve(instance)
|
|
25
|
+
@ivar ? instance.instance_variable_get(@ivar) : payload
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
module Steps
|
|
5
|
+
extend Lookup
|
|
6
|
+
|
|
7
|
+
INTERNAL = %w[Base Method Clause].freeze
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def build(name, *args, **kwargs, &block)
|
|
11
|
+
return build_clause(name, *args, **kwargs, &block) if block
|
|
12
|
+
|
|
13
|
+
(lookup(name) || Method).build(name, *args, **kwargs)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def lookup(name)
|
|
17
|
+
resolve(name, base: Base, except: INTERNAL)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def build_clause(name, *args, **kwargs, &block)
|
|
23
|
+
handler = Clauses.lookup(name)
|
|
24
|
+
unless handler
|
|
25
|
+
raise ArgumentError,
|
|
26
|
+
"unknown clause `#{name}`; define ThunderOperation::Clauses::#{name.to_s.camelize}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Clause.new(name, handler, *args, **kwargs, &block)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ThunderOperation
|
|
4
|
+
class StepsDefinition
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
MODULE_NAME = :StepMethods
|
|
8
|
+
|
|
9
|
+
class Methods < Module
|
|
10
|
+
attr_reader :names
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
super
|
|
14
|
+
@names = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def method_added(name)
|
|
18
|
+
super
|
|
19
|
+
@names << name unless @names.include?(name)
|
|
20
|
+
private(name)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_reader :owner, :methods_module
|
|
25
|
+
|
|
26
|
+
def self.build(owner, &block)
|
|
27
|
+
methods_module = methods_module_for(owner)
|
|
28
|
+
methods_module.class_exec(&block)
|
|
29
|
+
|
|
30
|
+
new(owner, methods_module)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.methods_module_for(owner)
|
|
34
|
+
return owner.const_get(MODULE_NAME, false) if owner.const_defined?(MODULE_NAME, false)
|
|
35
|
+
|
|
36
|
+
Methods.new.tap do |methods_module|
|
|
37
|
+
owner.const_set(MODULE_NAME, methods_module)
|
|
38
|
+
owner.include(methods_module)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
private_class_method :methods_module_for
|
|
42
|
+
|
|
43
|
+
def initialize(owner, methods_module)
|
|
44
|
+
@owner = owner
|
|
45
|
+
@methods_module = methods_module
|
|
46
|
+
freeze
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def names
|
|
50
|
+
methods_module.respond_to?(:names) ? methods_module.names : []
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def each(&)
|
|
54
|
+
names.each(&)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def include?(name)
|
|
58
|
+
names.include?(name.to_sym)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def instance_method(name)
|
|
62
|
+
methods_module.instance_method(name)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def empty?
|
|
66
|
+
names.empty?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def to_s
|
|
70
|
+
names.join(', ')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
NONE = new(nil, Module.new.freeze)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support'
|
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
|
5
|
+
require 'thunderframe'
|
|
6
|
+
|
|
7
|
+
require_relative 'thunderoperation/version'
|
|
8
|
+
require_relative 'thunderoperation/config'
|
|
9
|
+
require_relative 'thunderoperation/lookup'
|
|
10
|
+
require_relative 'thunderoperation/exceptions'
|
|
11
|
+
require_relative 'thunderoperation/exceptions/trail'
|
|
12
|
+
require_relative 'thunderoperation/response'
|
|
13
|
+
require_relative 'thunderoperation/handlers'
|
|
14
|
+
require_relative 'thunderoperation/adapter'
|
|
15
|
+
require_relative 'thunderoperation/concerns/has_adapter'
|
|
16
|
+
require_relative 'thunderoperation/parameters'
|
|
17
|
+
require_relative 'thunderoperation/parameters/base'
|
|
18
|
+
require_relative 'thunderoperation/parameters/hash_parameter'
|
|
19
|
+
require_relative 'thunderoperation/parameters/array_parameter'
|
|
20
|
+
require_relative 'thunderoperation/adapters/rich_parameters'
|
|
21
|
+
require_relative 'thunderoperation/adapters/interruptable'
|
|
22
|
+
require_relative 'thunderoperation/adapters/validations'
|
|
23
|
+
require_relative 'thunderoperation/adapters/framer'
|
|
24
|
+
require_relative 'thunderoperation/steps'
|
|
25
|
+
require_relative 'thunderoperation/steps/base'
|
|
26
|
+
require_relative 'thunderoperation/steps/method'
|
|
27
|
+
require_relative 'thunderoperation/steps/clause'
|
|
28
|
+
require_relative 'thunderoperation/steps/success'
|
|
29
|
+
require_relative 'thunderoperation/steps/render'
|
|
30
|
+
require_relative 'thunderoperation/clauses'
|
|
31
|
+
require_relative 'thunderoperation/clauses/base'
|
|
32
|
+
require_relative 'thunderoperation/clauses/transaction'
|
|
33
|
+
require_relative 'thunderoperation/flow'
|
|
34
|
+
require_relative 'thunderoperation/flow/builder'
|
|
35
|
+
require_relative 'thunderoperation/steps_definition'
|
|
36
|
+
require_relative 'thunderoperation/base'
|
metadata
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: thunderoperation
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Albert Alef
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activesupport
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '8.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '8.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: thunderframe
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - '='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 0.2.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - '='
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 0.2.0
|
|
40
|
+
executables: []
|
|
41
|
+
extensions: []
|
|
42
|
+
extra_rdoc_files: []
|
|
43
|
+
files:
|
|
44
|
+
- README.md
|
|
45
|
+
- config/default.yml
|
|
46
|
+
- lib/rubocop/cop/thunderoperation/call_handlers.rb
|
|
47
|
+
- lib/rubocop/cop/thunderoperation/def_outside_steps.rb
|
|
48
|
+
- lib/rubocop/cop/thunderoperation/flow_required.rb
|
|
49
|
+
- lib/rubocop/cop/thunderoperation/missing_steps.rb
|
|
50
|
+
- lib/rubocop/cop/thunderoperation/operation_helpers.rb
|
|
51
|
+
- lib/rubocop/cop/thunderoperation/operation_section_order.rb
|
|
52
|
+
- lib/rubocop/cop/thunderoperation/steps_cannot_call_steps.rb
|
|
53
|
+
- lib/rubocop/cop/thunderoperation/steps_order.rb
|
|
54
|
+
- lib/rubocop/cop/thunderoperation/unknown_step.rb
|
|
55
|
+
- lib/rubocop/cop/thunderoperation/unused_step.rb
|
|
56
|
+
- lib/thunderoperation.rb
|
|
57
|
+
- lib/thunderoperation/adapter.rb
|
|
58
|
+
- lib/thunderoperation/adapters/framer.rb
|
|
59
|
+
- lib/thunderoperation/adapters/interruptable.rb
|
|
60
|
+
- lib/thunderoperation/adapters/rich_parameters.rb
|
|
61
|
+
- lib/thunderoperation/adapters/validations.rb
|
|
62
|
+
- lib/thunderoperation/base.rb
|
|
63
|
+
- lib/thunderoperation/clauses.rb
|
|
64
|
+
- lib/thunderoperation/clauses/base.rb
|
|
65
|
+
- lib/thunderoperation/clauses/transaction.rb
|
|
66
|
+
- lib/thunderoperation/concerns/has_adapter.rb
|
|
67
|
+
- lib/thunderoperation/config.rb
|
|
68
|
+
- lib/thunderoperation/exceptions.rb
|
|
69
|
+
- lib/thunderoperation/exceptions/trail.rb
|
|
70
|
+
- lib/thunderoperation/flow.rb
|
|
71
|
+
- lib/thunderoperation/flow/builder.rb
|
|
72
|
+
- lib/thunderoperation/handlers.rb
|
|
73
|
+
- lib/thunderoperation/lookup.rb
|
|
74
|
+
- lib/thunderoperation/parameters.rb
|
|
75
|
+
- lib/thunderoperation/parameters/array_parameter.rb
|
|
76
|
+
- lib/thunderoperation/parameters/base.rb
|
|
77
|
+
- lib/thunderoperation/parameters/hash_parameter.rb
|
|
78
|
+
- lib/thunderoperation/response.rb
|
|
79
|
+
- lib/thunderoperation/rubocop.rb
|
|
80
|
+
- lib/thunderoperation/steps.rb
|
|
81
|
+
- lib/thunderoperation/steps/base.rb
|
|
82
|
+
- lib/thunderoperation/steps/clause.rb
|
|
83
|
+
- lib/thunderoperation/steps/method.rb
|
|
84
|
+
- lib/thunderoperation/steps/render.rb
|
|
85
|
+
- lib/thunderoperation/steps/success.rb
|
|
86
|
+
- lib/thunderoperation/steps_definition.rb
|
|
87
|
+
- lib/thunderoperation/version.rb
|
|
88
|
+
licenses: []
|
|
89
|
+
metadata:
|
|
90
|
+
rubygems_mfa_required: 'true'
|
|
91
|
+
rdoc_options: []
|
|
92
|
+
require_paths:
|
|
93
|
+
- lib
|
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - ">="
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: '3.4'
|
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
requirements: []
|
|
105
|
+
rubygems_version: 3.6.9
|
|
106
|
+
specification_version: 4
|
|
107
|
+
summary: 'Operations engine: param, flow, steps, returns, adapters'
|
|
108
|
+
test_files: []
|