grumlin 0.23.0 → 1.0.0.rc2

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -9
  3. data/Gemfile.lock +1 -1
  4. data/README.md +100 -142
  5. data/Rakefile +1 -1
  6. data/bin/console +18 -3
  7. data/doc/middlewares.md +49 -10
  8. data/lib/async/channel.rb +54 -56
  9. data/lib/grumlin/benchmark/repository.rb +10 -14
  10. data/lib/grumlin/client.rb +93 -95
  11. data/lib/grumlin/config.rb +33 -33
  12. data/lib/grumlin/dummy_transaction.rb +13 -15
  13. data/lib/grumlin/edge.rb +18 -20
  14. data/lib/grumlin/expressions/cardinality.rb +5 -9
  15. data/lib/grumlin/expressions/column.rb +5 -9
  16. data/lib/grumlin/expressions/expression.rb +7 -11
  17. data/lib/grumlin/expressions/operator.rb +5 -9
  18. data/lib/grumlin/expressions/order.rb +5 -9
  19. data/lib/grumlin/expressions/p.rb +27 -31
  20. data/lib/grumlin/expressions/pop.rb +5 -9
  21. data/lib/grumlin/expressions/scope.rb +5 -9
  22. data/lib/grumlin/expressions/t.rb +5 -9
  23. data/lib/grumlin/expressions/text_p.rb +5 -9
  24. data/lib/grumlin/expressions/with_options.rb +17 -21
  25. data/lib/grumlin/features/feature_list.rb +8 -12
  26. data/lib/grumlin/features/neptune_features.rb +5 -9
  27. data/lib/grumlin/features/tinkergraph_features.rb +5 -9
  28. data/lib/grumlin/features.rb +8 -10
  29. data/lib/grumlin/middlewares/apply_shortcuts.rb +4 -8
  30. data/lib/grumlin/middlewares/build_query.rb +16 -20
  31. data/lib/grumlin/middlewares/builder.rb +15 -0
  32. data/lib/grumlin/middlewares/cast_results.rb +3 -7
  33. data/lib/grumlin/middlewares/find_blocklisted_steps.rb +14 -0
  34. data/lib/grumlin/middlewares/find_mutating_steps.rb +9 -0
  35. data/lib/grumlin/middlewares/middleware.rb +6 -10
  36. data/lib/grumlin/middlewares/run_query.rb +3 -7
  37. data/lib/grumlin/middlewares/serialize_to_bytecode.rb +5 -9
  38. data/lib/grumlin/middlewares/serialize_to_steps.rb +4 -8
  39. data/lib/grumlin/path.rb +11 -13
  40. data/lib/grumlin/property.rb +14 -16
  41. data/lib/grumlin/query_validators/blocklisted_steps_validator.rb +22 -0
  42. data/lib/grumlin/query_validators/validator.rb +36 -0
  43. data/lib/grumlin/repository/error_handling_strategy.rb +36 -40
  44. data/lib/grumlin/repository/instance_methods.rb +115 -118
  45. data/lib/grumlin/repository.rb +82 -58
  46. data/lib/grumlin/request_dispatcher.rb +55 -57
  47. data/lib/grumlin/request_error_factory.rb +53 -55
  48. data/lib/grumlin/shortcut.rb +19 -21
  49. data/lib/grumlin/shortcuts/properties.rb +12 -16
  50. data/lib/grumlin/shortcuts/storage.rb +67 -74
  51. data/lib/grumlin/shortcuts/upserts.rb +19 -22
  52. data/lib/grumlin/shortcuts.rb +23 -25
  53. data/lib/grumlin/shortcuts_applyer.rb +27 -29
  54. data/lib/grumlin/step.rb +88 -90
  55. data/lib/grumlin/step_data.rb +12 -14
  56. data/lib/grumlin/steppable.rb +23 -25
  57. data/lib/grumlin/steps.rb +52 -54
  58. data/lib/grumlin/steps_serializers/bytecode.rb +53 -56
  59. data/lib/grumlin/steps_serializers/human_readable_bytecode.rb +17 -21
  60. data/lib/grumlin/steps_serializers/serializer.rb +7 -11
  61. data/lib/grumlin/steps_serializers/string.rb +26 -30
  62. data/lib/grumlin/test/rspec/db_cleaner_context.rb +8 -12
  63. data/lib/grumlin/test/rspec/gremlin_context.rb +18 -16
  64. data/lib/grumlin/test/rspec.rb +1 -5
  65. data/lib/grumlin/transaction.rb +34 -36
  66. data/lib/grumlin/transport.rb +71 -73
  67. data/lib/grumlin/traversal_start.rb +31 -33
  68. data/lib/grumlin/traversal_strategies/options_strategy.rb +3 -7
  69. data/lib/grumlin/traverser.rb +5 -7
  70. data/lib/grumlin/typed_value.rb +11 -13
  71. data/lib/grumlin/typing.rb +70 -72
  72. data/lib/grumlin/version.rb +1 -1
  73. data/lib/grumlin/vertex.rb +14 -16
  74. data/lib/grumlin/vertex_property.rb +14 -16
  75. data/lib/grumlin/with_extension.rb +17 -19
  76. data/lib/grumlin.rb +13 -0
  77. metadata +9 -6
  78. data/lib/grumlin/middlewares/frozen_builder.rb +0 -18
  79. data/lib/grumlin/sugar.rb +0 -15
@@ -1,73 +1,71 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class RequestErrorFactory
5
- ERRORS = {
6
- 499 => InvalidRequestArgumentsError,
7
- 500 => ServerError,
8
- 597 => ScriptEvaluationError,
9
- 599 => ServerSerializationError,
10
- 598 => ServerTimeoutError,
3
+ class Grumlin::RequestErrorFactory
4
+ ERRORS = {
5
+ 499 => Grumlin::InvalidRequestArgumentsError,
6
+ 500 => Grumlin::ServerError,
7
+ 597 => Grumlin::ScriptEvaluationError,
8
+ 599 => Grumlin::ServerSerializationError,
9
+ 598 => Grumlin::ServerTimeoutError,
11
10
 
12
- 401 => ClientSideError,
13
- 407 => ClientSideError,
14
- 498 => ClientSideError
15
- }.freeze
11
+ 401 => Grumlin::ClientSideError,
12
+ 407 => Grumlin::ClientSideError,
13
+ 498 => Grumlin::ClientSideError
14
+ }.freeze
16
15
 
17
- # Neptune presumably returns message as a JSON string of format
18
- # {"detailedMessage":"",
19
- # "requestId":"UUID",
20
- # "code":"ConcurrentModificationException"}
21
- # Currently we simply search for substrings to identify the exact error
22
- # TODO: parse json and use `code` instead
16
+ # Neptune presumably returns message as a JSON string of format
17
+ # {"detailedMessage":"",
18
+ # "requestId":"UUID",
19
+ # "code":"ConcurrentModificationException"}
20
+ # Currently we simply search for substrings to identify the exact error
21
+ # TODO: parse json and use `code` instead
23
22
 
24
- VERTEX_ALREADY_EXISTS = "Vertex with id already exists:"
25
- EDGE_ALREADY_EXISTS = "Edge with id already exists:"
23
+ VERTEX_ALREADY_EXISTS = "Vertex with id already exists:"
24
+ EDGE_ALREADY_EXISTS = "Edge with id already exists:"
26
25
 
27
- CONCURRENT_VERTEX_INSERT_FAILED = "Failed to complete Insert operation for a Vertex due to conflicting concurrent"
26
+ CONCURRENT_VERTEX_INSERT_FAILED = "Failed to complete Insert operation for a Vertex due to conflicting concurrent"
28
27
 
29
- CONCURRENT_VERTEX_PROPERTY_INSERT_FAILED =
30
- "Failed to complete Insert operation for a VertexProperty due to conflicting concurrent"
31
- CONCURRENT_EDGE_PROPERTY_INSERT_FAILED =
32
- "Failed to complete Insert operation for a EdgeProperty due to conflicting concurrent"
28
+ CONCURRENT_VERTEX_PROPERTY_INSERT_FAILED =
29
+ "Failed to complete Insert operation for a VertexProperty due to conflicting concurrent"
30
+ CONCURRENT_EDGE_PROPERTY_INSERT_FAILED =
31
+ "Failed to complete Insert operation for a EdgeProperty due to conflicting concurrent"
33
32
 
34
- CONCURRENT_EDGE_INSERT_FAILED = "Failed to complete Insert operation for an Edge due to conflicting concurrent"
35
- CONCURRENCT_MODIFICATION_FAILED = "Failed to complete operation due to conflicting concurrent"
33
+ CONCURRENT_EDGE_INSERT_FAILED = "Failed to complete Insert operation for an Edge due to conflicting concurrent"
34
+ CONCURRENCT_MODIFICATION_FAILED = "Failed to complete operation due to conflicting concurrent"
36
35
 
37
- class << self
38
- def build(request, response)
39
- status = response[:status]
40
- query = request[:request]
36
+ class << self
37
+ def build(request, response)
38
+ status = response[:status]
39
+ query = request[:request]
41
40
 
42
- if (error = ERRORS[status[:code]])
43
- return (
44
- already_exists_error(status) ||
45
- concurrent_modification_error(status) ||
46
- error
47
- ).new(status, query)
48
- end
41
+ if (error = ERRORS[status[:code]])
42
+ return (
43
+ already_exists_error(status) ||
44
+ concurrent_modification_error(status) ||
45
+ error
46
+ ).new(status, query)
47
+ end
49
48
 
50
- return unless RequestDispatcher::SUCCESS[status[:code]].nil?
49
+ return unless Grumlin::RequestDispatcher::SUCCESS[status[:code]].nil?
51
50
 
52
- UnknownResponseStatus.new(status)
53
- end
51
+ Grumlin::UnknownResponseStatus.new(status)
52
+ end
54
53
 
55
- def already_exists_error(status)
56
- return VertexAlreadyExistsError if status[:message]&.include?(VERTEX_ALREADY_EXISTS)
57
- return EdgeAlreadyExistsError if status[:message]&.include?(EDGE_ALREADY_EXISTS)
58
- end
54
+ def already_exists_error(status)
55
+ return Grumlin::VertexAlreadyExistsError if status[:message]&.include?(VERTEX_ALREADY_EXISTS)
56
+ return Grumlin::EdgeAlreadyExistsError if status[:message]&.include?(EDGE_ALREADY_EXISTS)
57
+ end
59
58
 
60
- def concurrent_modification_error(status) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
61
- return ConcurrentVertexInsertFailedError if status[:message]&.include?(CONCURRENT_VERTEX_INSERT_FAILED)
62
- if status[:message]&.include?(CONCURRENT_VERTEX_PROPERTY_INSERT_FAILED)
63
- return ConcurrentVertexPropertyInsertFailedError
64
- end
65
- return ConcurrentEdgeInsertFailedError if status[:message]&.include?(CONCURRENT_EDGE_INSERT_FAILED)
66
- if status[:message]&.include?(CONCURRENT_EDGE_PROPERTY_INSERT_FAILED)
67
- return ConcurrentEdgePropertyInsertFailedError
68
- end
69
- return ConcurrentModificationError if status[:message]&.include?(CONCURRENCT_MODIFICATION_FAILED)
59
+ def concurrent_modification_error(status) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
60
+ return Grumlin::ConcurrentVertexInsertFailedError if status[:message]&.include?(CONCURRENT_VERTEX_INSERT_FAILED)
61
+ if status[:message]&.include?(CONCURRENT_VERTEX_PROPERTY_INSERT_FAILED)
62
+ return Grumlin::ConcurrentVertexPropertyInsertFailedError
63
+ end
64
+ return Grumlin::ConcurrentEdgeInsertFailedError if status[:message]&.include?(CONCURRENT_EDGE_INSERT_FAILED)
65
+ if status[:message]&.include?(CONCURRENT_EDGE_PROPERTY_INSERT_FAILED)
66
+ return Grumlin::ConcurrentEdgePropertyInsertFailedError
70
67
  end
68
+ return Grumlin::ConcurrentModificationError if status[:message]&.include?(CONCURRENCT_MODIFICATION_FAILED)
71
69
  end
72
70
  end
73
71
  end
@@ -1,32 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class Shortcut
5
- extend Forwardable
3
+ class Grumlin::Shortcut
4
+ extend Forwardable
6
5
 
7
- attr_reader :name, :block
6
+ attr_reader :name, :block
8
7
 
9
- def_delegator :@block, :arity
10
- def_delegator :@block, :source_location
8
+ def_delegator :@block, :arity
9
+ def_delegator :@block, :source_location
11
10
 
12
- def initialize(name, lazy: true, &block)
13
- @name = name
14
- @lazy = lazy
15
- @block = block
16
- end
11
+ def initialize(name, lazy: true, &block)
12
+ @name = name
13
+ @lazy = lazy
14
+ @block = block
15
+ end
17
16
 
18
- def ==(other)
19
- @name == other.name && @block == other.block
20
- end
17
+ def ==(other)
18
+ @name == other.name && @block == other.block
19
+ end
21
20
 
22
- def lazy?
23
- @lazy
24
- end
21
+ def lazy?
22
+ @lazy
23
+ end
25
24
 
26
- # TODO: to_s, inspect, preview
25
+ # TODO: to_s, inspect, preview
27
26
 
28
- def apply(object, *args, **params)
29
- object.instance_exec(*args, **params, &@block)
30
- end
27
+ def apply(object, *args, **params)
28
+ object.instance_exec(*args, **params, &@block)
31
29
  end
32
30
  end
@@ -1,24 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Shortcuts
5
- module Properties
6
- extend Grumlin::Shortcuts
3
+ module Grumlin::Shortcuts::Properties
4
+ extend Grumlin::Shortcuts
7
5
 
8
- shortcut :props do |cardinality = nil, **props|
9
- props.reduce(self) do |tt, (prop, value)|
10
- next tt if value.nil? # nils are not supported
11
- next tt.property(prop, value) if cardinality.nil?
6
+ shortcut :props do |cardinality = nil, **props|
7
+ props.reduce(self) do |tt, (prop, value)|
8
+ next tt if value.nil? # nils are not supported
9
+ next tt.property(prop, value) if cardinality.nil?
12
10
 
13
- tt.property(cardinality, prop, value)
14
- end
15
- end
11
+ tt.property(cardinality, prop, value)
12
+ end
13
+ end
16
14
 
17
- shortcut :hasAll do |**props|
18
- props.reduce(self) do |tt, (prop, value)|
19
- tt.has(prop, value)
20
- end
21
- end
15
+ shortcut :hasAll do |**props|
16
+ props.reduce(self) do |tt, (prop, value)|
17
+ tt.has(prop, value)
22
18
  end
23
19
  end
24
20
  end
@@ -1,99 +1,92 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Shortcuts
5
- class Storage
6
- extend Forwardable
7
-
8
- class << self
9
- def [](other)
10
- new(other)
11
- end
3
+ class Grumlin::Shortcuts::Storage
4
+ extend Forwardable
12
5
 
13
- def empty
14
- @empty ||= new
15
- end
16
- end
6
+ class << self
7
+ def [](other)
8
+ new(other)
9
+ end
17
10
 
18
- def initialize(storage = {})
19
- @storage = storage
20
- storage.each do |n, s|
21
- add(n, s)
22
- end
23
- end
11
+ def empty
12
+ @empty ||= new
13
+ end
14
+ end
24
15
 
25
- def_delegator :@storage, :[]
26
- def_delegator :@storage, :include?, :known?
27
- def_delegator :@storage, :keys, :names
16
+ def initialize(storage = {})
17
+ @storage = storage
18
+ storage.each do |n, s|
19
+ add(n, s)
20
+ end
21
+ end
28
22
 
29
- def ==(other)
30
- @storage == other.storage
31
- end
23
+ def_delegator :@storage, :[]
24
+ def_delegator :@storage, :include?, :known?
25
+ def_delegator :@storage, :keys, :names
26
+ def_delegator :self, :__, :g
32
27
 
33
- def add(name, shortcut)
34
- @storage[name] = shortcut
28
+ def ==(other)
29
+ @storage == other.storage
30
+ end
35
31
 
36
- sc = step_class
32
+ def add(name, shortcut)
33
+ @storage[name] = shortcut
37
34
 
38
- shortcut_methods_module.define_method(name) do |*args, **params|
39
- next sc.new(name, args: args, params: params, previous_step: self, pool: Grumlin.default_pool)
40
- end
41
- extend_traversal_classes(shortcut) unless shortcut.lazy?
42
- end
35
+ sc = step_class
43
36
 
44
- def add_from(other)
45
- other.storage.each do |name, shortcut|
46
- add(name, shortcut)
47
- end
48
- end
37
+ shortcut_methods_module.define_method(name) do |*args, **params|
38
+ next sc.new(name, args: args, params: params, previous_step: self, pool: Grumlin.default_pool)
39
+ end
40
+ extend_traversal_classes(shortcut) unless shortcut.lazy?
41
+ end
49
42
 
50
- def g
51
- __
52
- end
43
+ def add_from(other)
44
+ other.storage.each do |name, shortcut|
45
+ add(name, shortcut)
46
+ end
47
+ end
53
48
 
54
- def __
55
- traversal_start_class.new(pool: Grumlin.default_pool)
56
- end
49
+ def __
50
+ traversal_start_class.new(pool: Grumlin.default_pool)
51
+ end
57
52
 
58
- def traversal_start_class
59
- @traversal_start_class ||= shortcut_aware_class(TraversalStart)
60
- end
53
+ def traversal_start_class
54
+ @traversal_start_class ||= shortcut_aware_class(Grumlin::TraversalStart)
55
+ end
61
56
 
62
- def step_class
63
- @step_class ||= shortcut_aware_class(Step)
64
- end
57
+ def step_class
58
+ @step_class ||= shortcut_aware_class(Grumlin::Step)
59
+ end
65
60
 
66
- protected
61
+ protected
67
62
 
68
- attr_reader :storage
63
+ attr_reader :storage
69
64
 
70
- private
65
+ private
71
66
 
72
- def shortcut_methods_module
73
- @shortcut_methods_module ||= begin
74
- shorts = self
75
- Module.new do
76
- define_method :shortcuts do
77
- shorts
78
- end
79
- end
67
+ def shortcut_methods_module
68
+ @shortcut_methods_module ||= begin
69
+ shorts = self
70
+ Module.new do
71
+ define_method :shortcuts do
72
+ shorts
80
73
  end
81
74
  end
75
+ end
76
+ end
82
77
 
83
- def shortcut_aware_class(base)
84
- methods = shortcut_methods_module
85
- Class.new(base) do
86
- include methods
87
- end
88
- end
78
+ def shortcut_aware_class(base)
79
+ methods = shortcut_methods_module
80
+ Class.new(base) do
81
+ include methods
82
+ end
83
+ end
89
84
 
90
- def extend_traversal_classes(shortcut)
91
- m = Module.new do
92
- define_method(shortcut.name, &shortcut.block)
93
- end
94
- step_class.include(m)
95
- traversal_start_class.include(m)
96
- end
85
+ def extend_traversal_classes(shortcut)
86
+ m = Module.new do
87
+ define_method(shortcut.name, &shortcut.block)
97
88
  end
89
+ step_class.include(m)
90
+ traversal_start_class.include(m)
98
91
  end
99
92
  end
@@ -1,28 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Shortcuts
5
- module Upserts
6
- extend Grumlin::Shortcuts
3
+ module Grumlin::Shortcuts::Upserts
4
+ extend Grumlin::Shortcuts
7
5
 
8
- shortcut :upsertV do |label, id, create_properties = {}, update_properties = {}|
9
- self.V(id)
10
- .fold
11
- .coalesce(
12
- __.unfold,
13
- __.addV(label).props(Cardinality.single, **create_properties.merge(T.id => id))
14
- ).props(Cardinality.single, **update_properties)
15
- end
6
+ shortcut :upsertV do |label, id, create_properties = {}, update_properties = {}|
7
+ self.V(id)
8
+ .fold
9
+ .coalesce(
10
+ __.unfold,
11
+ __.addV(label).props(Cardinality.single, **create_properties.merge(T.id => id))
12
+ ).props(Cardinality.single, **update_properties)
13
+ end
16
14
 
17
- shortcut :upsertE do |label, from, to, create_properties = {}, update_properties = {}|
18
- self.V(from)
19
- .outE(label).where(__.inV.hasId(to))
20
- .fold
21
- .coalesce(
22
- __.unfold,
23
- __.addE(label).from(__.V(from)).to(__.V(to)).props(**create_properties)
24
- ).props(**update_properties)
25
- end
26
- end
15
+ shortcut :upsertE do |label, from, to, create_properties = {}, update_properties = {}|
16
+ id = create_properties[T.id] || Grumlin.fake_uuid(from, label, to)
17
+ self.V(from)
18
+ .outE(label).where(__.inV.hasId(to))
19
+ .fold
20
+ .coalesce(
21
+ __.unfold,
22
+ __.addE(label).from(__.V(from)).to(__.V(to)).props(**create_properties.merge(T.id => id))
23
+ ).props(**update_properties)
27
24
  end
28
25
  end
@@ -1,36 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Shortcuts
5
- def self.extended(base)
6
- base.include(Grumlin::Expressions)
7
- end
3
+ module Grumlin::Shortcuts
4
+ def self.extended(base)
5
+ base.include(Grumlin::Expressions)
6
+ end
8
7
 
9
- def inherited(subclass)
10
- super
11
- subclass.shortcuts_from(self)
12
- end
8
+ def inherited(subclass)
9
+ super
10
+ subclass.shortcuts_from(self)
11
+ end
13
12
 
14
- def shortcut(name, shortcut = nil, override: false, lazy: true, &block)
15
- name = name.to_sym
16
- lazy = false if override
13
+ def shortcut(name, shortcut = nil, override: false, lazy: true, &block)
14
+ name = name.to_sym
15
+ lazy = false if override
17
16
 
18
- if Grumlin::Step::REGULAR_STEPS.include?(name) && !override
19
- raise ArgumentError,
20
- "overriding standard gremlin steps is not allowed, if you know what you're doing, pass `override: true`"
21
- end
17
+ if Grumlin::Step::REGULAR_STEPS.include?(name) && !override
18
+ raise ArgumentError,
19
+ "overriding standard gremlin steps is not allowed, if you know what you're doing, pass `override: true`"
20
+ end
22
21
 
23
- raise ArgumentError, "either shortcut or block must be passed" if [shortcut, block].count(&:nil?) != 1
22
+ raise ArgumentError, "either shortcut or block must be passed" if [shortcut, block].count(&:nil?) != 1
24
23
 
25
- shortcuts.add(name, shortcut || Shortcut.new(name, lazy: lazy, &block))
26
- end
24
+ shortcuts.add(name, shortcut || Grumlin::Shortcut.new(name, lazy: lazy, &block))
25
+ end
27
26
 
28
- def shortcuts_from(other_shortcuts)
29
- shortcuts.add_from(other_shortcuts.shortcuts)
30
- end
27
+ def shortcuts_from(other_shortcuts)
28
+ shortcuts.add_from(other_shortcuts.shortcuts)
29
+ end
31
30
 
32
- def shortcuts
33
- @shortcuts ||= Storage.new
34
- end
31
+ def shortcuts
32
+ @shortcuts ||= Storage.new
35
33
  end
36
34
  end
@@ -1,41 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class ShortcutsApplyer
5
- class << self
6
- def call(steps)
7
- return steps if !steps.is_a?(Steps) || !steps.uses_shortcuts?
8
-
9
- shortcuts = steps.shortcuts
10
-
11
- steps = [
12
- *process_steps(steps.configuration_steps, shortcuts),
13
- *process_steps(steps.steps, shortcuts)
14
- ]
15
-
16
- Steps.new(shortcuts).tap do |processed_steps|
17
- steps.each do |step|
18
- processed_steps.add(step.name, args: step.args, params: step.params)
19
- end
3
+ class Grumlin::ShortcutsApplyer
4
+ class << self
5
+ def call(steps)
6
+ return steps if !steps.is_a?(Grumlin::Steps) || !steps.uses_shortcuts?
7
+
8
+ shortcuts = steps.shortcuts
9
+
10
+ steps = [
11
+ *process_steps(steps.configuration_steps, shortcuts),
12
+ *process_steps(steps.steps, shortcuts)
13
+ ]
14
+
15
+ Grumlin::Steps.new(shortcuts).tap do |processed_steps|
16
+ steps.each do |step|
17
+ processed_steps.add(step.name, args: step.args, params: step.params)
20
18
  end
21
19
  end
20
+ end
22
21
 
23
- private
22
+ private
24
23
 
25
- def process_steps(steps, shortcuts) # rubocop:disable Metrics/AbcSize
26
- steps.each_with_object([]) do |step, result|
27
- args = step.args.map { |arg| call(arg) }
24
+ def process_steps(steps, shortcuts) # rubocop:disable Metrics/AbcSize
25
+ steps.each_with_object([]) do |step, result|
26
+ args = step.args.map { |arg| call(arg) }
28
27
 
29
- shortcut = shortcuts[step.name]
30
- next result << StepData.new(step.name, args: args, params: step.params) unless shortcut&.lazy?
28
+ shortcut = shortcuts[step.name]
29
+ next result << Grumlin::StepData.new(step.name, args: args, params: step.params) unless shortcut&.lazy?
31
30
 
32
- t = shortcuts.__
33
- step = shortcut.apply(t, *args, **step.params)
34
- next if step.nil? || step == t # Shortcut did not add any steps
31
+ t = shortcuts.__
32
+ step = shortcut.apply(t, *args, **step.params)
33
+ next if step.nil? || step == t # Shortcut did not add any steps
35
34
 
36
- new_steps = call(Steps.from(step))
37
- result.concat(new_steps.configuration_steps, new_steps.steps)
38
- end
35
+ new_steps = call(Grumlin::Steps.from(step))
36
+ result.concat(new_steps.configuration_steps, new_steps.steps)
39
37
  end
40
38
  end
41
39
  end