grumlin 0.23.0 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -9
  3. data/Gemfile.lock +1 -1
  4. data/README.md +94 -141
  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 +18 -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. metadata +9 -6
  77. data/lib/grumlin/middlewares/frozen_builder.rb +0 -18
  78. 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,24 @@
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
+ self.V(from)
17
+ .outE(label).where(__.inV.hasId(to))
18
+ .fold
19
+ .coalesce(
20
+ __.unfold,
21
+ __.addE(label).from(__.V(from)).to(__.V(to)).props(**create_properties)
22
+ ).props(**update_properties)
27
23
  end
28
24
  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