strum 0.0.56 → 0.1.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 +4 -4
- data/Gemfile.lock +6 -6
- data/bin/console +15 -0
- data/lib/strum.rb +1 -1
- data/lib/strum/json_schema.rb +102 -0
- data/lib/strum/pipe.rb +20 -11
- data/lib/strum/service.rb +24 -23
- data/lib/strum/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e42ae1ed242ca62b4424ebeb549eaccbd54f3b66348fb31bc7d65f457efdf1a0
|
4
|
+
data.tar.gz: a86f1a2c6d32b9c211b68702514411da590801ecbc6637b40a5a88f9d47f6699
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfa1308d4b365e7ab7a0d945dadcc0289908e8e17760d2cde18741a3206ebd618d4d300250f92158825906a0c472866474084c24151da7e12baad9b670b3448f
|
7
|
+
data.tar.gz: 64482d3661a03579d1944723969d74e7b2f4c582e0e3386eb05391ab6796c6740e5acf8c95452c156fe2d05c5cdf8ac604a84261623166a5697a4b8c2e591bec
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
strum (0.0
|
4
|
+
strum (0.1.0)
|
5
5
|
dry-inflector (~> 0.2.0)
|
6
6
|
dry-struct (~> 1.2)
|
7
7
|
json-schema (~> 2.8.1)
|
@@ -16,7 +16,7 @@ GEM
|
|
16
16
|
ast (2.4.0)
|
17
17
|
concurrent-ruby (1.1.6)
|
18
18
|
diff-lcs (1.3)
|
19
|
-
dry-configurable (0.11.
|
19
|
+
dry-configurable (0.11.5)
|
20
20
|
concurrent-ruby (~> 1.0)
|
21
21
|
dry-core (~> 0.4, >= 0.4.7)
|
22
22
|
dry-equalizer (~> 0.2)
|
@@ -36,7 +36,7 @@ GEM
|
|
36
36
|
dry-equalizer (~> 0.3)
|
37
37
|
dry-types (~> 1.3)
|
38
38
|
ice_nine (~> 0.11)
|
39
|
-
dry-types (1.
|
39
|
+
dry-types (1.4.0)
|
40
40
|
concurrent-ruby (~> 1.0)
|
41
41
|
dry-container (~> 0.3)
|
42
42
|
dry-core (~> 0.4, >= 0.4.4)
|
@@ -51,7 +51,7 @@ GEM
|
|
51
51
|
json-schema (2.8.1)
|
52
52
|
addressable (>= 2.4)
|
53
53
|
parallel (1.19.1)
|
54
|
-
parser (2.7.0.
|
54
|
+
parser (2.7.0.5)
|
55
55
|
ast (~> 2.4.0)
|
56
56
|
public_suffix (4.0.3)
|
57
57
|
rainbow (3.0.0)
|
@@ -64,7 +64,7 @@ GEM
|
|
64
64
|
rspec-mocks (~> 3.9.0)
|
65
65
|
rspec-core (3.9.1)
|
66
66
|
rspec-support (~> 3.9.1)
|
67
|
-
rspec-expectations (3.9.
|
67
|
+
rspec-expectations (3.9.1)
|
68
68
|
diff-lcs (>= 1.2.0, < 2.0)
|
69
69
|
rspec-support (~> 3.9.0)
|
70
70
|
rspec-mocks (3.9.1)
|
@@ -79,7 +79,7 @@ GEM
|
|
79
79
|
ruby-progressbar (~> 1.7)
|
80
80
|
unicode-display_width (>= 1.4.0, < 1.7)
|
81
81
|
ruby-progressbar (1.10.1)
|
82
|
-
sequel (5.
|
82
|
+
sequel (5.30.0)
|
83
83
|
sequel-annotate (1.4.0)
|
84
84
|
sequel (>= 4)
|
85
85
|
thor (0.20.3)
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "strum"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/lib/strum.rb
CHANGED
@@ -0,0 +1,102 @@
|
|
1
|
+
require "strum/service"
|
2
|
+
require "json-schema"
|
3
|
+
|
4
|
+
module Strum
|
5
|
+
module JsonSchema
|
6
|
+
class Validate
|
7
|
+
include Strum::Service
|
8
|
+
|
9
|
+
def call
|
10
|
+
array_errors = JSON::Validator.fully_validate(args[:schema], input, errors_as_objects: true)
|
11
|
+
array_errors.each { |error| add_error(*self.parse_json_schema_error(error)) }
|
12
|
+
output(input)
|
13
|
+
end
|
14
|
+
|
15
|
+
def audit
|
16
|
+
add_error(:schema, :not_found) if !args[:schema].is_a?(Hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def parse_json_schema_error(error)
|
22
|
+
id = error[:fragment].sub(/#/, "input")
|
23
|
+
keys = id.split("/")
|
24
|
+
last_key_idx = keys.rindex { |key| key !~ /[0-9]+/ }
|
25
|
+
last_key = keys.map { |key| key =~ /[0-9]+/ ? "[#{key}]" : ".#{key}" }.join[1..-1]
|
26
|
+
value = error[:message][0, error[:message].index(/ in schema/)].sub(error[:fragment], last_key)
|
27
|
+
[last_key.to_sym, value]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Cast
|
32
|
+
include Strum::Service
|
33
|
+
|
34
|
+
def call
|
35
|
+
output(casted(input, args[:schema]))
|
36
|
+
end
|
37
|
+
|
38
|
+
def audit
|
39
|
+
add_error(:schema, :not_found) if !args[:schema].is_a?(Hash)
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def casted(input_data, schema)
|
45
|
+
@input_data = input_data
|
46
|
+
|
47
|
+
def rec_casted(schema, path = [])
|
48
|
+
item = self.custom_dig(@input_data, path)
|
49
|
+
|
50
|
+
if item.is_a?(NoValue)
|
51
|
+
return item
|
52
|
+
end
|
53
|
+
|
54
|
+
case schema[:type]
|
55
|
+
when Array
|
56
|
+
schema[:type].reduce(nil) do |type, x|
|
57
|
+
new_schema = schema.clone
|
58
|
+
new_schema[:type] = x
|
59
|
+
type ||= rec_casted(new_schema, path)
|
60
|
+
end
|
61
|
+
when "object"
|
62
|
+
if item.is_a?(Hash) && schema[:properties].is_a?(Hash)
|
63
|
+
schema[:properties].map { |key, val| [key, rec_casted(val, path + [key])] }.filter { |pair| !pair[1].is_a?(NoValue) }.to_h
|
64
|
+
end
|
65
|
+
when "array"
|
66
|
+
if item.is_a?(Array) && schema[:items].is_a?(Hash)
|
67
|
+
(0..(item.length - 1)).reduce([]) { |res, idx| res << rec_casted(schema[:items], path + [idx]) }
|
68
|
+
end
|
69
|
+
when "string"
|
70
|
+
item.to_s
|
71
|
+
when "integer"
|
72
|
+
if item.is_a?(Numeric)
|
73
|
+
item
|
74
|
+
elsif item.is_a?(String) || item.is_a?(Symbol)
|
75
|
+
item.to_s.to_i
|
76
|
+
end
|
77
|
+
when "boolean"
|
78
|
+
item.to_s.downcase == "true"
|
79
|
+
when "jsonb"
|
80
|
+
if (Module.constants.include?(:Sequel)) && (Sequel.methods.include?(:pg_jsonb_wrap))
|
81
|
+
Sequel.pg_jsonb_wrap(item)
|
82
|
+
else
|
83
|
+
add_error(:schema, "jsonb type is not supported")
|
84
|
+
end
|
85
|
+
when nil, ""
|
86
|
+
item
|
87
|
+
else
|
88
|
+
add_error(:schema, :invalid_type)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
rec_casted(schema)
|
93
|
+
end
|
94
|
+
|
95
|
+
def custom_dig(obj, path)
|
96
|
+
path.reduce(obj) { |item, x| item.fetch(x) { |it| return NoValue.new } }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class NoValue; end
|
101
|
+
end
|
102
|
+
end
|
data/lib/strum/pipe.rb
CHANGED
@@ -4,13 +4,13 @@ module Strum
|
|
4
4
|
class Pipe
|
5
5
|
include Strum::Service
|
6
6
|
|
7
|
-
def self.call(*units, input: {}, unit_input: {}, &block)
|
7
|
+
def self.call(*units, args: {}, input: {}, unit_input: {}, &block)
|
8
8
|
pipe_payload = if input.is_a?(Hash) && unit_input.is_a?(Hash)
|
9
9
|
unit_input.merge(input)
|
10
10
|
else
|
11
11
|
input
|
12
12
|
end
|
13
|
-
new(pipe_payload).execute(*units, input, unit_input, &block)
|
13
|
+
new(pipe_payload, args).execute(*units, input, unit_input, &block)
|
14
14
|
end
|
15
15
|
|
16
16
|
def execute(*units, pipe_inputs, pipe_unit_inputs, &block)
|
@@ -24,6 +24,15 @@ module Strum
|
|
24
24
|
raise Strum::Error, "Unit options must be a Hash" unless service_params.is_a?(Hash)
|
25
25
|
|
26
26
|
service_options = service_params[:input] || {}
|
27
|
+
result_place = service_params[:to]
|
28
|
+
unit_args = case service_params[:args]
|
29
|
+
when Hash
|
30
|
+
service_params[:args]
|
31
|
+
when Symbol, String
|
32
|
+
{ service_params[:args] => service_params[:args] }
|
33
|
+
else
|
34
|
+
{}
|
35
|
+
end
|
27
36
|
clean_output = service_params[:clean_output] || false
|
28
37
|
unit_payload = if !clean_output && service_options.is_a?(Hash) && pipe_unit_inputs.is_a?(Hash) && output_value.is_a?(Hash)
|
29
38
|
pipe_unit_inputs.merge(service_options).merge(output_value)
|
@@ -31,21 +40,21 @@ module Strum
|
|
31
40
|
output_value
|
32
41
|
end
|
33
42
|
|
34
|
-
service.public_send(:call, unit_payload) do |m|
|
35
|
-
service_handlers[:on].each do |
|
36
|
-
m.on(
|
43
|
+
service.public_send(:call, unit_payload, args.merge(unit_args)) do |m|
|
44
|
+
service_handlers[:on].each do |key, _handler|
|
45
|
+
m.on(key) { |r| hook(k, r) }
|
37
46
|
end
|
38
47
|
|
39
|
-
service_handlers[:success].each do |
|
40
|
-
if
|
41
|
-
m.success(
|
42
|
-
output(
|
48
|
+
service_handlers[:success].each do |key, _handler|
|
49
|
+
if key
|
50
|
+
m.success(key) do |result|
|
51
|
+
output(key, result)
|
43
52
|
continue = false
|
44
53
|
end
|
45
54
|
else
|
46
55
|
m.success do |result|
|
47
|
-
if
|
48
|
-
|
56
|
+
if result_place
|
57
|
+
inputs[result_place] = result
|
49
58
|
elsif !clean_output && result.is_a?(Hash) && output_value.is_a?(Hash)
|
50
59
|
output(output_value.merge(result))
|
51
60
|
else
|
data/lib/strum/service.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require "json-schema"
|
3
2
|
|
4
3
|
module Strum
|
5
4
|
# Module
|
@@ -14,19 +13,18 @@ module Strum
|
|
14
13
|
|
15
14
|
# Internal: Interactor class methods.
|
16
15
|
module ClassMethods
|
17
|
-
def call(_input
|
18
|
-
new(_input).execute(&block)
|
16
|
+
def call(_input, **args, &block)
|
17
|
+
new(_input, args).execute(&block)
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
21
|
# Instance methods
|
23
|
-
def initialize(_input)
|
22
|
+
def initialize(_input, **args)
|
24
23
|
self.strum_errors = {}
|
25
24
|
self.service_handlers = { on: {}, success: {}, failure: {} }
|
26
25
|
self.outputs = {}
|
27
|
-
self.
|
28
|
-
self.
|
29
|
-
self.input = self._input.dup
|
26
|
+
self.inputs = args.merge(default: _input)
|
27
|
+
self._inputs = inputs.dup.freeze
|
30
28
|
end
|
31
29
|
|
32
30
|
def execute
|
@@ -72,7 +70,7 @@ module Strum
|
|
72
70
|
|
73
71
|
protected
|
74
72
|
|
75
|
-
attr_accessor :
|
73
|
+
attr_accessor :inputs, :_inputs, :strum_errors, :outputs, :service_handlers
|
76
74
|
|
77
75
|
def call
|
78
76
|
raise Failure, "call method must be implemented"
|
@@ -80,6 +78,22 @@ module Strum
|
|
80
78
|
|
81
79
|
def audit; end
|
82
80
|
|
81
|
+
def input
|
82
|
+
inputs[:default]
|
83
|
+
end
|
84
|
+
|
85
|
+
def input=(value)
|
86
|
+
inputs[:default] = value
|
87
|
+
end
|
88
|
+
|
89
|
+
def _input
|
90
|
+
_inputs[:default]
|
91
|
+
end
|
92
|
+
|
93
|
+
def args
|
94
|
+
inputs.slice(*inputs.keys - [:default])
|
95
|
+
end
|
96
|
+
|
83
97
|
def output_value(key = :default)
|
84
98
|
@outputs[key]
|
85
99
|
end
|
@@ -122,7 +136,7 @@ module Strum
|
|
122
136
|
|
123
137
|
def sliced(*keys)
|
124
138
|
if input.is_a?(Hash)
|
125
|
-
|
139
|
+
self.input = input.slice(*keys)
|
126
140
|
else
|
127
141
|
add_error(:input, :must_be_hash)
|
128
142
|
end
|
@@ -130,7 +144,7 @@ module Strum
|
|
130
144
|
|
131
145
|
def sliced_list(*keys)
|
132
146
|
if input.is_a?(Array)
|
133
|
-
|
147
|
+
self.input = input.map do |item|
|
134
148
|
if item.is_a?(Hash)
|
135
149
|
item = item.slice(*keys)
|
136
150
|
else
|
@@ -142,19 +156,6 @@ module Strum
|
|
142
156
|
end
|
143
157
|
end
|
144
158
|
|
145
|
-
def validated(schema:, list: false)
|
146
|
-
array_errors = JSON::Validator.fully_validate(schema, @input, errors_as_objects: true, list: list)
|
147
|
-
array_errors.each{|error| add_error(*self.parse_json_schema_error(error))}
|
148
|
-
end
|
149
|
-
|
150
|
-
def parse_json_schema_error(error)
|
151
|
-
pos_match = error[:fragment].match(/([0-9]+)[\/]?/)
|
152
|
-
pos = pos_match.is_a?(Array) ? pos_match[1] : "_"
|
153
|
-
key = error[:fragment].sub(/#\//, "").sub(/([0-9]+)[\/]?/, "")
|
154
|
-
value = "Item ##{pos}. " + error[:message][0, error[:message].index(/ in schema/)].sub(/#\//, "").sub(/([0-9]+)[\/]?/, "")
|
155
|
-
[key.to_sym, value]
|
156
|
-
end
|
157
|
-
|
158
159
|
def array!
|
159
160
|
self.input = [*input]
|
160
161
|
end
|
data/lib/strum/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Serhiy Nazarov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|
@@ -181,6 +181,7 @@ files:
|
|
181
181
|
- Gemfile.lock
|
182
182
|
- README.md
|
183
183
|
- Rakefile
|
184
|
+
- bin/console
|
184
185
|
- bin/strum
|
185
186
|
- lib/strum.rb
|
186
187
|
- lib/strum/Rakefile
|
@@ -201,6 +202,7 @@ files:
|
|
201
202
|
- lib/strum/deep_keys_to_sym.rb
|
202
203
|
- lib/strum/json.rb
|
203
204
|
- lib/strum/json_deserializer.rb
|
205
|
+
- lib/strum/json_schema.rb
|
204
206
|
- lib/strum/json_serializer.rb
|
205
207
|
- lib/strum/object_to_hash.rb
|
206
208
|
- lib/strum/pipe.rb
|