flows 0.2.0 → 0.6.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/.github/workflows/{build.yml → test.yml} +5 -10
- data/.gitignore +9 -1
- data/.mdlrc +1 -1
- data/.reek.yml +54 -0
- data/.rubocop.yml +26 -7
- data/.rubocop_todo.yml +27 -0
- data/.ruby-version +1 -1
- data/.yardopts +1 -0
- data/CHANGELOG.md +81 -0
- data/Gemfile +0 -6
- data/README.md +167 -363
- data/Rakefile +35 -1
- data/bin/.rubocop.yml +5 -0
- data/bin/all_the_errors +55 -0
- data/bin/benchmark +73 -105
- data/bin/benchmark_cli/compare.rb +118 -0
- data/bin/benchmark_cli/compare/a_plus_b.rb +22 -0
- data/bin/benchmark_cli/compare/base.rb +45 -0
- data/bin/benchmark_cli/compare/command.rb +47 -0
- data/bin/benchmark_cli/compare/ten_steps.rb +22 -0
- data/bin/benchmark_cli/examples.rb +23 -0
- data/bin/benchmark_cli/examples/.rubocop.yml +22 -0
- data/bin/benchmark_cli/examples/a_plus_b/dry_do.rb +23 -0
- data/bin/benchmark_cli/examples/a_plus_b/dry_transaction.rb +17 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_do.rb +22 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_railway.rb +13 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_scp.rb +13 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_scp_mut.rb +13 -0
- data/bin/benchmark_cli/examples/a_plus_b/flows_scp_oc.rb +21 -0
- data/bin/benchmark_cli/examples/a_plus_b/trailblazer.rb +15 -0
- data/bin/benchmark_cli/examples/ten_steps/dry_do.rb +70 -0
- data/bin/benchmark_cli/examples/ten_steps/dry_transaction.rb +64 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_do.rb +69 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_railway.rb +58 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_scp.rb +58 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_scp_mut.rb +58 -0
- data/bin/benchmark_cli/examples/ten_steps/flows_scp_oc.rb +66 -0
- data/bin/benchmark_cli/examples/ten_steps/trailblazer.rb +60 -0
- data/bin/benchmark_cli/helpers.rb +12 -0
- data/bin/benchmark_cli/ruby.rb +15 -0
- data/bin/benchmark_cli/ruby/command.rb +38 -0
- data/bin/benchmark_cli/ruby/method_exec.rb +71 -0
- data/bin/benchmark_cli/ruby/self_class.rb +69 -0
- data/bin/benchmark_cli/ruby/structs.rb +90 -0
- data/bin/console +1 -0
- data/bin/docserver +7 -0
- data/bin/errors +138 -0
- data/bin/errors_cli/contract_error_demo.rb +49 -0
- data/bin/errors_cli/di_error_demo.rb +38 -0
- data/bin/errors_cli/flow_error_demo.rb +22 -0
- data/bin/errors_cli/flows_router_error_demo.rb +15 -0
- data/bin/errors_cli/interface_error_demo.rb +17 -0
- data/bin/errors_cli/oc_error_demo.rb +40 -0
- data/bin/errors_cli/railway_error_demo.rb +10 -0
- data/bin/errors_cli/result_error_demo.rb +13 -0
- data/bin/errors_cli/scp_error_demo.rb +17 -0
- data/docs/README.md +3 -187
- data/docs/_sidebar.md +0 -24
- data/docs/index.html +1 -1
- data/flows.gemspec +27 -2
- data/forspell.dict +9 -0
- data/lefthook.yml +9 -0
- data/lib/flows.rb +11 -5
- data/lib/flows/contract.rb +402 -0
- data/lib/flows/contract/array.rb +55 -0
- data/lib/flows/contract/case_eq.rb +43 -0
- data/lib/flows/contract/compose.rb +77 -0
- data/lib/flows/contract/either.rb +53 -0
- data/lib/flows/contract/error.rb +24 -0
- data/lib/flows/contract/hash.rb +75 -0
- data/lib/flows/contract/hash_of.rb +70 -0
- data/lib/flows/contract/helpers.rb +22 -0
- data/lib/flows/contract/predicate.rb +34 -0
- data/lib/flows/contract/transformer.rb +50 -0
- data/lib/flows/contract/tuple.rb +70 -0
- data/lib/flows/flow.rb +96 -7
- data/lib/flows/flow/errors.rb +29 -0
- data/lib/flows/flow/node.rb +132 -0
- data/lib/flows/flow/router.rb +29 -0
- data/lib/flows/flow/router/custom.rb +59 -0
- data/lib/flows/flow/router/errors.rb +11 -0
- data/lib/flows/flow/router/simple.rb +25 -0
- data/lib/flows/plugin.rb +15 -0
- data/lib/flows/plugin/dependency_injector.rb +170 -0
- data/lib/flows/plugin/dependency_injector/dependency.rb +24 -0
- data/lib/flows/plugin/dependency_injector/dependency_definition.rb +16 -0
- data/lib/flows/plugin/dependency_injector/dependency_list.rb +55 -0
- data/lib/flows/plugin/dependency_injector/errors.rb +58 -0
- data/lib/flows/plugin/implicit_init.rb +45 -0
- data/lib/flows/plugin/interface.rb +84 -0
- data/lib/flows/plugin/output_contract.rb +85 -0
- data/lib/flows/plugin/output_contract/dsl.rb +48 -0
- data/lib/flows/plugin/output_contract/errors.rb +74 -0
- data/lib/flows/plugin/output_contract/wrapper.rb +55 -0
- data/lib/flows/plugin/profiler.rb +114 -0
- data/lib/flows/plugin/profiler/injector.rb +35 -0
- data/lib/flows/plugin/profiler/report.rb +48 -0
- data/lib/flows/plugin/profiler/report/events.rb +43 -0
- data/lib/flows/plugin/profiler/report/flat.rb +41 -0
- data/lib/flows/plugin/profiler/report/flat/method_report.rb +80 -0
- data/lib/flows/plugin/profiler/report/raw.rb +15 -0
- data/lib/flows/plugin/profiler/report/tree.rb +98 -0
- data/lib/flows/plugin/profiler/report/tree/calculated_node.rb +116 -0
- data/lib/flows/plugin/profiler/report/tree/node.rb +34 -0
- data/lib/flows/plugin/profiler/wrapper.rb +53 -0
- data/lib/flows/railway.rb +140 -34
- data/lib/flows/railway/dsl.rb +8 -18
- data/lib/flows/railway/errors.rb +8 -12
- data/lib/flows/railway/step.rb +24 -0
- data/lib/flows/railway/step_list.rb +38 -0
- data/lib/flows/result.rb +188 -2
- data/lib/flows/result/do.rb +158 -16
- data/lib/flows/result/err.rb +12 -6
- data/lib/flows/result/errors.rb +29 -17
- data/lib/flows/result/helpers.rb +25 -3
- data/lib/flows/result/ok.rb +12 -6
- data/lib/flows/shared_context_pipeline.rb +342 -0
- data/lib/flows/shared_context_pipeline/dsl.rb +12 -0
- data/lib/flows/shared_context_pipeline/dsl/callbacks.rb +35 -0
- data/lib/flows/shared_context_pipeline/dsl/tracks.rb +52 -0
- data/lib/flows/shared_context_pipeline/errors.rb +17 -0
- data/lib/flows/shared_context_pipeline/mutation_step.rb +30 -0
- data/lib/flows/shared_context_pipeline/router_definition.rb +21 -0
- data/lib/flows/shared_context_pipeline/step.rb +55 -0
- data/lib/flows/shared_context_pipeline/track.rb +54 -0
- data/lib/flows/shared_context_pipeline/track_list.rb +51 -0
- data/lib/flows/shared_context_pipeline/wrap.rb +73 -0
- data/lib/flows/util.rb +17 -0
- data/lib/flows/util/inheritable_singleton_vars.rb +86 -0
- data/lib/flows/util/inheritable_singleton_vars/dup_strategy.rb +100 -0
- data/lib/flows/util/inheritable_singleton_vars/isolation_strategy.rb +91 -0
- data/lib/flows/util/prepend_to_class.rb +191 -0
- data/lib/flows/version.rb +1 -1
- metadata +253 -38
- data/Gemfile.lock +0 -174
- data/bin/demo +0 -66
- data/bin/examples.rb +0 -195
- data/bin/profile_10steps +0 -106
- data/bin/ruby_benchmarks +0 -26
- data/docs/CNAME +0 -1
- data/docs/contributing/benchmarks_profiling.md +0 -3
- data/docs/contributing/local_development.md +0 -3
- data/docs/flow/direct_usage.md +0 -3
- data/docs/flow/general_idea.md +0 -3
- data/docs/operation/basic_usage.md +0 -1
- data/docs/operation/inject_steps.md +0 -3
- data/docs/operation/lambda_steps.md +0 -3
- data/docs/operation/result_shapes.md +0 -3
- data/docs/operation/routing_tracks.md +0 -3
- data/docs/operation/wrapping_steps.md +0 -3
- data/docs/overview/performance.md +0 -336
- data/docs/railway/basic_usage.md +0 -232
- data/docs/result_objects/basic_usage.md +0 -196
- data/docs/result_objects/do_notation.md +0 -139
- data/lib/flows/node.rb +0 -27
- data/lib/flows/operation.rb +0 -52
- data/lib/flows/operation/builder.rb +0 -130
- data/lib/flows/operation/builder/build_router.rb +0 -37
- data/lib/flows/operation/dsl.rb +0 -93
- data/lib/flows/operation/errors.rb +0 -75
- data/lib/flows/operation/executor.rb +0 -78
- data/lib/flows/railway/builder.rb +0 -68
- data/lib/flows/railway/executor.rb +0 -23
- data/lib/flows/result_router.rb +0 -14
- data/lib/flows/router.rb +0 -22
| @@ -1,37 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              module Operation
         | 
| 3 | 
            -
                class Builder
         | 
| 4 | 
            -
                  # Router builder
         | 
| 5 | 
            -
                  module BuildRouter
         | 
| 6 | 
            -
                    class << self
         | 
| 7 | 
            -
                      def call(custom_routes, next_step, step_names)
         | 
| 8 | 
            -
                        if custom_routes
         | 
| 9 | 
            -
                          custom_router(custom_routes, next_step, step_names)
         | 
| 10 | 
            -
                        else
         | 
| 11 | 
            -
                          Flows::ResultRouter.new(next_step, :term)
         | 
| 12 | 
            -
                        end
         | 
| 13 | 
            -
                      end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                      private
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                      def custom_router(custom_routes, next_step, step_names)
         | 
| 18 | 
            -
                        check_custom_routes(custom_routes, step_names)
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                        custom_routes[Flows::Result::Ok] ||= next_step
         | 
| 21 | 
            -
                        custom_routes[Flows::Result::Err] ||= :term
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                        Flows::Router.new(custom_routes)
         | 
| 24 | 
            -
                      end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                      def check_custom_routes(custom_routes, step_names)
         | 
| 27 | 
            -
                        custom_routes.values.each do |target|
         | 
| 28 | 
            -
                          next if step_names.include?(target) || target == :term
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                          raise(::Flows::Operation::NoStepDefinedError, target)
         | 
| 31 | 
            -
                        end
         | 
| 32 | 
            -
                      end
         | 
| 33 | 
            -
                    end
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
                end
         | 
| 36 | 
            -
              end
         | 
| 37 | 
            -
            end
         | 
    
        data/lib/flows/operation/dsl.rb
    DELETED
    
    | @@ -1,93 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              module Operation
         | 
| 3 | 
            -
                # DSL methods for operation
         | 
| 4 | 
            -
                module DSL
         | 
| 5 | 
            -
                  attr_reader :steps, :ok_shapes, :err_shapes
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                  def self.extended(mod, steps = nil, ok_shapes = nil, err_shapes = nil)
         | 
| 8 | 
            -
                    mod.instance_variable_set(:@steps, steps || [])
         | 
| 9 | 
            -
                    mod.instance_variable_set(:@track_path, [])
         | 
| 10 | 
            -
                    mod.instance_variable_set(:@ok_shapes, ok_shapes)
         | 
| 11 | 
            -
                    mod.instance_variable_set(:@err_shapes, err_shapes)
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                    mod.class_exec do
         | 
| 14 | 
            -
                      def self.inherited(subclass)
         | 
| 15 | 
            -
                        ::Flows::Operation::DSL.extended(subclass, steps.map(&:dup), ok_shapes, err_shapes)
         | 
| 16 | 
            -
                        super
         | 
| 17 | 
            -
                      end
         | 
| 18 | 
            -
                    end
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  include Flows::Result::Helpers
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                  def step(name, custom_body_or_routes = nil, custom_routes = nil)
         | 
| 24 | 
            -
                    if custom_routes
         | 
| 25 | 
            -
                      custom_body = custom_body_or_routes
         | 
| 26 | 
            -
                    elsif custom_body_or_routes.is_a? Hash
         | 
| 27 | 
            -
                      custom_routes = custom_body_or_routes
         | 
| 28 | 
            -
                      custom_body = nil
         | 
| 29 | 
            -
                    else
         | 
| 30 | 
            -
                      custom_routes = nil
         | 
| 31 | 
            -
                      custom_body = custom_body_or_routes
         | 
| 32 | 
            -
                    end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                    @steps << make_step(name, custom_routes: custom_routes, custom_body: custom_body)
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  def track(name, &block)
         | 
| 38 | 
            -
                    track_path_before = @track_path
         | 
| 39 | 
            -
                    @track_path += [name]
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    @steps << make_step(name, custom_body: ->(**) { ok })
         | 
| 42 | 
            -
                    instance_exec(&block)
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                    @track_path = track_path_before
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  def routes(routes_hash)
         | 
| 48 | 
            -
                    routes_hash
         | 
| 49 | 
            -
                  end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                  alias when_ok match_ok
         | 
| 52 | 
            -
                  alias when_err match_err
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                  def wrap(name, custom_body = nil, &block)
         | 
| 55 | 
            -
                    @steps << make_step(name, type: :wrapper, custom_body: custom_body, block: block)
         | 
| 56 | 
            -
                  end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                  def ok_shape(*keys, **code_keys_map)
         | 
| 59 | 
            -
                    @ok_shapes = if keys.empty?
         | 
| 60 | 
            -
                                   code_keys_map
         | 
| 61 | 
            -
                                 else
         | 
| 62 | 
            -
                                   { success: keys }
         | 
| 63 | 
            -
                                 end
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                  def err_shape(*keys, **code_keys_map)
         | 
| 67 | 
            -
                    @err_shapes = if keys.empty?
         | 
| 68 | 
            -
                                    code_keys_map
         | 
| 69 | 
            -
                                  else
         | 
| 70 | 
            -
                                    { failure: keys }
         | 
| 71 | 
            -
                                  end
         | 
| 72 | 
            -
                  end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                  def no_shape
         | 
| 75 | 
            -
                    @ok_shapes = :no_shapes
         | 
| 76 | 
            -
                    @err_shapes = :no_shapes
         | 
| 77 | 
            -
                  end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                  private
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  def make_step(name, type: :step, custom_routes: {}, custom_body: nil, block: nil)
         | 
| 82 | 
            -
                    {
         | 
| 83 | 
            -
                      type: type,
         | 
| 84 | 
            -
                      name: name,
         | 
| 85 | 
            -
                      custom_routes: custom_routes,
         | 
| 86 | 
            -
                      custom_body: custom_body,
         | 
| 87 | 
            -
                      block: block,
         | 
| 88 | 
            -
                      track_path: @track_path
         | 
| 89 | 
            -
                    }
         | 
| 90 | 
            -
                  end
         | 
| 91 | 
            -
                end
         | 
| 92 | 
            -
              end
         | 
| 93 | 
            -
            end
         | 
| @@ -1,75 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              module Operation
         | 
| 3 | 
            -
                # rubocop:disable Style/Documentation
         | 
| 4 | 
            -
                class NoSuccessShapeError < ::Flows::Error
         | 
| 5 | 
            -
                  def message
         | 
| 6 | 
            -
                    'Missing success output shapes'
         | 
| 7 | 
            -
                  end
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                class NoFailureShapeError < ::Flows::Error
         | 
| 11 | 
            -
                  def message
         | 
| 12 | 
            -
                    'Missing failure output shape'
         | 
| 13 | 
            -
                  end
         | 
| 14 | 
            -
                end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                class NoStepsError < ::Flows::Error
         | 
| 17 | 
            -
                  def message
         | 
| 18 | 
            -
                    'No steps defined'
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                class NoStepImplementationError < ::Flows::Error
         | 
| 23 | 
            -
                  def initialize(step_name)
         | 
| 24 | 
            -
                    @step_name = step_name
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                  def message
         | 
| 28 | 
            -
                    "Missing step implementation for #{@step_name}"
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                class NoStepDefinedError < ::Flows::Error
         | 
| 33 | 
            -
                  def initialize(step_name)
         | 
| 34 | 
            -
                    @step_name = step_name
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  def message
         | 
| 38 | 
            -
                    "Missing step or track definition: #{@step_name}"
         | 
| 39 | 
            -
                  end
         | 
| 40 | 
            -
                end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                class MissingOutputError < ::Flows::Error
         | 
| 43 | 
            -
                  def initialize(required_keys, actual_keys)
         | 
| 44 | 
            -
                    @missing_keys = required_keys - actual_keys
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  def message
         | 
| 48 | 
            -
                    "Missing keys in output: #{@missing_keys.join(', ')}"
         | 
| 49 | 
            -
                  end
         | 
| 50 | 
            -
                end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                class UnexpectedSuccessStatusError < ::Flows::Error
         | 
| 53 | 
            -
                  def initialize(actual_status, supported_statuses)
         | 
| 54 | 
            -
                    @actual_status = actual_status.inspect
         | 
| 55 | 
            -
                    @supported_statuses = supported_statuses.map(&:inspect).join(', ')
         | 
| 56 | 
            -
                  end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                  def message
         | 
| 59 | 
            -
                    "Unexpeted success result status: `#{@actual_status}`, supported statuses: `#{@supported_statuses}`"
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
                end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                class UnexpectedFailureStatusError < ::Flows::Error
         | 
| 64 | 
            -
                  def initialize(actual_status, supported_statuses)
         | 
| 65 | 
            -
                    @actual_status = actual_status.inspect
         | 
| 66 | 
            -
                    @supported_statuses = supported_statuses.map(&:inspect).join(', ')
         | 
| 67 | 
            -
                  end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  def message
         | 
| 70 | 
            -
                    "Unexpeted failure result status: `#{@actual_status}`, supported statuses: `#{@supported_statuses}`"
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
                end
         | 
| 73 | 
            -
                # rubocop:enable Style/Documentation
         | 
| 74 | 
            -
              end
         | 
| 75 | 
            -
            end
         | 
| @@ -1,78 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              module Operation
         | 
| 3 | 
            -
                # Runner for operation steps
         | 
| 4 | 
            -
                class Executor
         | 
| 5 | 
            -
                  include ::Flows::Result::Helpers
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                  def initialize(flow:, ok_shapes:, err_shapes:, class_name:)
         | 
| 8 | 
            -
                    @flow = flow
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                    @ok_shapes = ok_shapes
         | 
| 11 | 
            -
                    @err_shapes = err_shapes
         | 
| 12 | 
            -
                    @operation_class_name = class_name
         | 
| 13 | 
            -
                  end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  def call(**params)
         | 
| 16 | 
            -
                    context = { data: params }
         | 
| 17 | 
            -
                    last_result = @flow.call(nil, context: context)
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                    build_result(last_result, context)
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  private
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  def build_result(last_result, context)
         | 
| 25 | 
            -
                    status = last_result.status
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                    case last_result
         | 
| 28 | 
            -
                    when Flows::Result::Ok then build_success_result(status, context)
         | 
| 29 | 
            -
                    when Flows::Result::Err then build_failure_result(status, context, last_result)
         | 
| 30 | 
            -
                    end
         | 
| 31 | 
            -
                  end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  def build_success_result(status, context)
         | 
| 34 | 
            -
                    return ok(status, context[:data]) if @ok_shapes == :no_shapes
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                    shape = @ok_shapes[status]
         | 
| 37 | 
            -
                    raise ::Flows::Operation::UnexpectedSuccessStatusError.new(status, @ok_shapes.keys) if shape.nil?
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                    data = extract_data(context[:data], shape)
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    ok(status, data)
         | 
| 42 | 
            -
                  end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                  def build_failure_result(status, context, last_result)
         | 
| 45 | 
            -
                    raise ::Flows::Operation::NoFailureShapeError if @err_shapes.nil?
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                    meta = build_meta(context, last_result)
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                    return Flows::Result::Err.new(context[:data], status: status, meta: meta) if @err_shapes == :no_shapes
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                    shape = @err_shapes[status]
         | 
| 52 | 
            -
                    raise ::Flows::Operation::UnexpectedFailureStatusError.new(status, @err_shapes.keys) if shape.nil?
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                    data = extract_data(context[:data], shape)
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                    Flows::Result::Err.new(data, status: status, meta: meta)
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                  def extract_data(output, keys)
         | 
| 60 | 
            -
                    raise ::Flows::Operation::MissingOutputError.new(keys, output.keys) unless keys.all? { |key| output.key?(key) }
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                    output.slice(*keys)
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                  def build_meta(context, last_result)
         | 
| 66 | 
            -
                    meta = {
         | 
| 67 | 
            -
                      operation: @operation_class_name,
         | 
| 68 | 
            -
                      step: context[:last_step],
         | 
| 69 | 
            -
                      context_data: context[:data]
         | 
| 70 | 
            -
                    }
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                    meta[:nested_metadata] = last_result.meta if last_result.meta.any?
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                    meta
         | 
| 75 | 
            -
                  end
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
              end
         | 
| 78 | 
            -
            end
         | 
| @@ -1,68 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              module Railway
         | 
| 3 | 
            -
                # Flow builder
         | 
| 4 | 
            -
                class Builder
         | 
| 5 | 
            -
                  attr_reader :steps, :method_source, :deps
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                  def initialize(steps:, method_source:, deps:)
         | 
| 8 | 
            -
                    @method_source = method_source
         | 
| 9 | 
            -
                    @steps = steps
         | 
| 10 | 
            -
                    @deps = deps
         | 
| 11 | 
            -
                  end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                  def call
         | 
| 14 | 
            -
                    resolve_bodies_and_wiring!
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                    nodes = build_nodes
         | 
| 17 | 
            -
                    Flows::Flow.new(start_node: nodes.first.name, nodes: nodes)
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  private
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  def resolve_bodies_and_wiring!
         | 
| 23 | 
            -
                    index = 0
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                    while index < @steps.length
         | 
| 26 | 
            -
                      current_step = @steps[index]
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                      current_step[:next_step] = @steps[index + 1]&.fetch(:name) || :term
         | 
| 29 | 
            -
                      current_step[:body] = current_step[:custom_body] || resolve_body_from_source(current_step[:name])
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                      index += 1
         | 
| 32 | 
            -
                    end
         | 
| 33 | 
            -
                  end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  def resolve_body_from_source(name)
         | 
| 36 | 
            -
                    return @deps[name] if @deps.key?(name)
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                    raise(::Flows::Railway::NoStepImplementationError, name) unless @method_source.respond_to?(name)
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                    @method_source.method(name)
         | 
| 41 | 
            -
                  end
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  def build_nodes
         | 
| 44 | 
            -
                    @nodes = @steps.map do |step|
         | 
| 45 | 
            -
                      Flows::Node.new(
         | 
| 46 | 
            -
                        name: step[:name],
         | 
| 47 | 
            -
                        body: step[:body],
         | 
| 48 | 
            -
                        preprocessor: method(:node_preprocessor),
         | 
| 49 | 
            -
                        postprocessor: method(:node_postprocessor),
         | 
| 50 | 
            -
                        router: Flows::ResultRouter.new(step[:next_step], :term),
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                        meta: { name: step[:name] }
         | 
| 53 | 
            -
                      )
         | 
| 54 | 
            -
                    end
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                  def node_preprocessor(input, _context, _meta)
         | 
| 58 | 
            -
                    input.unwrap
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  def node_postprocessor(output, context, meta)
         | 
| 62 | 
            -
                    context[:last_step] = meta[:name]
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                    output
         | 
| 65 | 
            -
                  end
         | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
              end
         | 
| 68 | 
            -
            end
         | 
| @@ -1,23 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              module Railway
         | 
| 3 | 
            -
                # Runner for railway steps
         | 
| 4 | 
            -
                class Executor
         | 
| 5 | 
            -
                  include ::Flows::Result::Helpers
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                  def initialize(flow:, class_name:)
         | 
| 8 | 
            -
                    @flow = flow
         | 
| 9 | 
            -
                    @railway_class_name = class_name
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  def call(**params)
         | 
| 13 | 
            -
                    context = {}
         | 
| 14 | 
            -
                    last_result = @flow.call(ok(params), context: context)
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                    last_result.meta[:railway] = @railway_class_name
         | 
| 17 | 
            -
                    last_result.meta[:last_step] = context[:last_step]
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                    last_result
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
              end
         | 
| 23 | 
            -
            end
         | 
    
        data/lib/flows/result_router.rb
    DELETED
    
    | @@ -1,14 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              # Node router for simple case when result must be a `Flows::Result`
         | 
| 3 | 
            -
              # and we don't care about result status key
         | 
| 4 | 
            -
              class ResultRouter
         | 
| 5 | 
            -
                def initialize(success_route, failure_route)
         | 
| 6 | 
            -
                  @success_route = success_route
         | 
| 7 | 
            -
                  @failure_route = failure_route
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                def call(output, **)
         | 
| 11 | 
            -
                  output.ok? ? @success_route : @failure_route
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
              end
         | 
| 14 | 
            -
            end
         | 
    
        data/lib/flows/router.rb
    DELETED
    
    | @@ -1,22 +0,0 @@ | |
| 1 | 
            -
            module Flows
         | 
| 2 | 
            -
              # Node router: defines predicate rules to calculate next node.
         | 
| 3 | 
            -
              class Router
         | 
| 4 | 
            -
                class Error < Flows::Error; end
         | 
| 5 | 
            -
                class NoRouteError < Error; end
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                def initialize(route_hash, preprocessor: nil)
         | 
| 8 | 
            -
                  @route_def = route_hash
         | 
| 9 | 
            -
                  @preprocessor = preprocessor
         | 
| 10 | 
            -
                end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                def call(output, context:, meta:)
         | 
| 13 | 
            -
                  data = @preprocessor ? @preprocessor.call(output, context, meta) : output
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  @route_def.each_pair do |predicate, route|
         | 
| 16 | 
            -
                    return route if predicate === data # rubocop:disable Style/CaseEquality
         | 
| 17 | 
            -
                  end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  raise NoRouteError, "no route found found for output: #{output.inspect}"
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
              end
         | 
| 22 | 
            -
            end
         |