teckel 0.1.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/CHANGELOG.md +114 -0
- data/LICENSE_LOGO +4 -0
- data/README.md +22 -14
- data/lib/teckel.rb +11 -2
- data/lib/teckel/chain.rb +47 -152
- data/lib/teckel/chain/config.rb +246 -0
- data/lib/teckel/chain/result.rb +38 -0
- data/lib/teckel/chain/runner.rb +62 -0
- data/lib/teckel/chain/step.rb +18 -0
- data/lib/teckel/config.rb +41 -52
- data/lib/teckel/contracts.rb +19 -0
- data/lib/teckel/operation.rb +108 -253
- data/lib/teckel/operation/config.rb +396 -0
- data/lib/teckel/operation/result.rb +92 -0
- data/lib/teckel/operation/runner.rb +75 -0
- data/lib/teckel/result.rb +52 -53
- data/lib/teckel/version.rb +1 -1
- data/spec/chain/default_settings_spec.rb +39 -0
- data/spec/chain/inheritance_spec.rb +116 -0
- data/spec/chain/none_input_spec.rb +36 -0
- data/spec/chain/results_spec.rb +53 -0
- data/spec/chain_around_hook_spec.rb +100 -0
- data/spec/chain_spec.rb +180 -0
- data/spec/config_spec.rb +26 -0
- data/spec/doctest_helper.rb +7 -0
- data/spec/operation/contract_trace_spec.rb +116 -0
- data/spec/operation/default_settings_spec.rb +94 -0
- data/spec/operation/inheritance_spec.rb +94 -0
- data/spec/operation/result_spec.rb +34 -0
- data/spec/operation/results_spec.rb +117 -0
- data/spec/operation_spec.rb +483 -0
- data/spec/rb27/pattern_matching_spec.rb +193 -0
- data/spec/result_spec.rb +22 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/dry_base.rb +8 -0
- data/spec/support/fake_db.rb +12 -0
- data/spec/support/fake_models.rb +20 -0
- data/spec/teckel_spec.rb +7 -0
- metadata +64 -46
- data/.github/workflows/ci.yml +0 -67
- data/.github/workflows/pages.yml +0 -50
- data/.gitignore +0 -13
- data/.rspec +0 -3
- data/.rubocop.yml +0 -12
- data/.ruby-version +0 -1
- data/DEVELOPMENT.md +0 -28
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -71
- data/Rakefile +0 -30
- data/bin/console +0 -15
- data/bin/rake +0 -29
- data/bin/rspec +0 -29
- data/bin/rubocop +0 -18
- data/bin/setup +0 -8
- data/lib/teckel/operation/results.rb +0 -71
- data/teckel.gemspec +0 -33
data/.github/workflows/ci.yml
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
name: CI
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
paths:
|
6
|
-
- .github/workflows/ci.yml
|
7
|
-
- lib/**
|
8
|
-
- spec/**
|
9
|
-
- Gemfile
|
10
|
-
- "*.gemspec"
|
11
|
-
- ".rubocop.yml"
|
12
|
-
|
13
|
-
jobs:
|
14
|
-
rubocop:
|
15
|
-
runs-on: ubuntu-latest
|
16
|
-
steps:
|
17
|
-
- uses: actions/checkout@v1
|
18
|
-
- name: Set up Ruby
|
19
|
-
uses: actions/setup-ruby@v1
|
20
|
-
with:
|
21
|
-
ruby-version: 2.4.x
|
22
|
-
- name: Install bundler
|
23
|
-
run: gem install bundler
|
24
|
-
- name: Run rubocop
|
25
|
-
run: bin/rubocop -ESD
|
26
|
-
|
27
|
-
cruby:
|
28
|
-
runs-on: ubuntu-latest
|
29
|
-
strategy:
|
30
|
-
fail-fast: false
|
31
|
-
matrix:
|
32
|
-
ruby: ["2.6.x", "2.5.x", "2.4.x"]
|
33
|
-
|
34
|
-
steps:
|
35
|
-
- uses: actions/checkout@v1
|
36
|
-
- name: Set up Ruby
|
37
|
-
uses: actions/setup-ruby@v1
|
38
|
-
with:
|
39
|
-
ruby-version: ${{matrix.ruby}}
|
40
|
-
- name: Bundle install
|
41
|
-
run: |
|
42
|
-
gem install bundler
|
43
|
-
bundle install --jobs 4 --retry 3 --without tools docs benchmarks
|
44
|
-
- name: Run all tests
|
45
|
-
run: bundle exec rake
|
46
|
-
|
47
|
-
other-ruby:
|
48
|
-
runs-on: ubuntu-latest
|
49
|
-
strategy:
|
50
|
-
fail-fast: false
|
51
|
-
matrix:
|
52
|
-
image: ["jruby:9.2.9", "ruby:2.7"]
|
53
|
-
container:
|
54
|
-
image: ${{matrix.image}}
|
55
|
-
|
56
|
-
steps:
|
57
|
-
- uses: actions/checkout@v1
|
58
|
-
- name: Install git
|
59
|
-
run: |
|
60
|
-
apt-get update
|
61
|
-
apt-get install -y --no-install-recommends git
|
62
|
-
- name: Bundle install
|
63
|
-
run: |
|
64
|
-
gem install bundler
|
65
|
-
bundle install --jobs 4 --retry 3 --without tools docs benchmarks
|
66
|
-
- name: Run all tests
|
67
|
-
run: bundle exec rake
|
data/.github/workflows/pages.yml
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
name: pages
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches:
|
6
|
-
- master
|
7
|
-
paths:
|
8
|
-
- .github/workflows/pages.yml
|
9
|
-
- lib/**
|
10
|
-
- README.md
|
11
|
-
- .yardopts
|
12
|
-
- Rakefile
|
13
|
-
|
14
|
-
jobs:
|
15
|
-
build-docs:
|
16
|
-
runs-on: ubuntu-latest
|
17
|
-
steps:
|
18
|
-
- uses: actions/checkout@v2
|
19
|
-
- name: Set up Ruby
|
20
|
-
uses: actions/setup-ruby@v1
|
21
|
-
with:
|
22
|
-
ruby-version: 2.6.x
|
23
|
-
- name: Bundle install
|
24
|
-
run: |
|
25
|
-
gem install bundler
|
26
|
-
bundle install --jobs 4 --retry 3 --without tools docs benchmarks
|
27
|
-
- name: Build docs
|
28
|
-
run: 'bin/rake docs:yard'
|
29
|
-
- name: config git
|
30
|
-
run: |
|
31
|
-
git config --local user.email "action@github.com"
|
32
|
-
git config --local user.name "GitHub Action"
|
33
|
-
- name: Checkout Pages
|
34
|
-
run: 'git fetch origin gh-pages && git checkout gh-pages'
|
35
|
-
- name: Replace and commit docs
|
36
|
-
run: |
|
37
|
-
rm -rf doc && mv _yardoc doc
|
38
|
-
git add -A doc
|
39
|
-
git commit -m"Update API docs"
|
40
|
-
- name: Replace index
|
41
|
-
run: |
|
42
|
-
git checkout master README.md
|
43
|
-
mv -f README.md index.md
|
44
|
-
if [ ! -z "$(git diff --name-only -- index.md)" ]; then
|
45
|
-
git commit index.md -m"update index"
|
46
|
-
fi
|
47
|
-
- name: Push
|
48
|
-
env:
|
49
|
-
INPUT_GITHUB_TOKEN: "${{ secrets.DEPLOY_TOKEN }}"
|
50
|
-
run: git push https://git:${INPUT_GITHUB_TOKEN}@github.com/fnordfish/teckel.git gh-pages
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.rubocop.yml
DELETED
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby-2.6.5
|
data/DEVELOPMENT.md
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# Development Guidelines
|
2
|
-
|
3
|
-
- Keep is simple.
|
4
|
-
- Favor easy debug-ability over clever solutions.
|
5
|
-
- Aim to be a 0-dependency lib (at runtime)
|
6
|
-
|
7
|
-
## Roadmap
|
8
|
-
|
9
|
-
- Add "Settings" for Operations and Chains
|
10
|
-
|
11
|
-
```
|
12
|
-
MyOp.with(foo: "bar").call("input")
|
13
|
-
|
14
|
-
class MyOp
|
15
|
-
settings Types::Hash.schema(foo: Types::String)
|
16
|
-
|
17
|
-
def call(input)
|
18
|
-
input == "input"
|
19
|
-
settings.foo == "bar"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
MyCain.with(:step1) { { foo: "bar" } }.with(:stepX) { { another: :setting} }.call(params)
|
24
|
-
```
|
25
|
-
- Add support for around hooks in Chains (for db transactions etc.)
|
26
|
-
- Add a dry-monads mixin to wrap Operations and Chains result/error into a Result Monad
|
27
|
-
- ...
|
28
|
-
|
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
teckel (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
concurrent-ruby (1.1.5)
|
10
|
-
diff-lcs (1.3)
|
11
|
-
dry-configurable (0.9.0)
|
12
|
-
concurrent-ruby (~> 1.0)
|
13
|
-
dry-core (~> 0.4, >= 0.4.7)
|
14
|
-
dry-container (0.7.2)
|
15
|
-
concurrent-ruby (~> 1.0)
|
16
|
-
dry-configurable (~> 0.1, >= 0.1.3)
|
17
|
-
dry-core (0.4.9)
|
18
|
-
concurrent-ruby (~> 1.0)
|
19
|
-
dry-equalizer (0.3.0)
|
20
|
-
dry-inflector (0.2.0)
|
21
|
-
dry-logic (1.0.5)
|
22
|
-
concurrent-ruby (~> 1.0)
|
23
|
-
dry-core (~> 0.2)
|
24
|
-
dry-equalizer (~> 0.2)
|
25
|
-
dry-struct (1.2.0)
|
26
|
-
dry-core (~> 0.4, >= 0.4.3)
|
27
|
-
dry-equalizer (~> 0.3)
|
28
|
-
dry-types (~> 1.0)
|
29
|
-
ice_nine (~> 0.11)
|
30
|
-
dry-types (1.2.2)
|
31
|
-
concurrent-ruby (~> 1.0)
|
32
|
-
dry-container (~> 0.3)
|
33
|
-
dry-core (~> 0.4, >= 0.4.4)
|
34
|
-
dry-equalizer (~> 0.3)
|
35
|
-
dry-inflector (~> 0.1, >= 0.1.2)
|
36
|
-
dry-logic (~> 1.0, >= 1.0.2)
|
37
|
-
ice_nine (0.11.2)
|
38
|
-
minitest (5.13.0)
|
39
|
-
rake (13.0.1)
|
40
|
-
rspec (3.9.0)
|
41
|
-
rspec-core (~> 3.9.0)
|
42
|
-
rspec-expectations (~> 3.9.0)
|
43
|
-
rspec-mocks (~> 3.9.0)
|
44
|
-
rspec-core (3.9.1)
|
45
|
-
rspec-support (~> 3.9.1)
|
46
|
-
rspec-expectations (3.9.0)
|
47
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
48
|
-
rspec-support (~> 3.9.0)
|
49
|
-
rspec-mocks (3.9.1)
|
50
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
51
|
-
rspec-support (~> 3.9.0)
|
52
|
-
rspec-support (3.9.2)
|
53
|
-
yard (0.9.22)
|
54
|
-
yard-doctest (0.1.17)
|
55
|
-
minitest
|
56
|
-
yard
|
57
|
-
|
58
|
-
PLATFORMS
|
59
|
-
ruby
|
60
|
-
|
61
|
-
DEPENDENCIES
|
62
|
-
bundler (~> 2.0)
|
63
|
-
dry-struct (>= 1.1.1, < 2)
|
64
|
-
rake (>= 10.0)
|
65
|
-
rspec (~> 3.0)
|
66
|
-
teckel!
|
67
|
-
yard
|
68
|
-
yard-doctest
|
69
|
-
|
70
|
-
BUNDLED WITH
|
71
|
-
2.1.2
|
data/Rakefile
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bundler/gem_tasks"
|
4
|
-
require "rspec/core/rake_task"
|
5
|
-
require "yard"
|
6
|
-
require "yard/doctest/rake"
|
7
|
-
|
8
|
-
RSpec::Core::RakeTask.new(:spec)
|
9
|
-
|
10
|
-
namespace :docs do
|
11
|
-
YARD::Rake::YardocTask.new do |t|
|
12
|
-
t.files = ['lib/**/*.rb']
|
13
|
-
t.options = []
|
14
|
-
t.stats_options = ['--list-undoc']
|
15
|
-
end
|
16
|
-
|
17
|
-
task :fswatch do
|
18
|
-
sh 'fswatch -0 lib | while read -d "" e; do rake docs:yard; done'
|
19
|
-
end
|
20
|
-
|
21
|
-
YARD::Doctest::RakeTask.new do |task|
|
22
|
-
task.doctest_opts = %w[-v]
|
23
|
-
task.pattern = Dir.glob('lib/**/*.rb')
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
task :default do
|
28
|
-
Rake::Task["spec"].invoke
|
29
|
-
Rake::Task["docs:yard:doctest"].invoke
|
30
|
-
end
|
data/bin/console
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "bundler/setup"
|
5
|
-
require "teckel"
|
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/bin/rake
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rake' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
-
Pathname.new(__FILE__).realpath)
|
14
|
-
|
15
|
-
bundle_binstub = File.expand_path('bundle', __dir__)
|
16
|
-
|
17
|
-
if File.file?(bundle_binstub)
|
18
|
-
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
-
load(bundle_binstub)
|
20
|
-
else
|
21
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
require "rubygems"
|
27
|
-
require "bundler/setup"
|
28
|
-
|
29
|
-
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# This file was generated by Bundler.
|
6
|
-
#
|
7
|
-
# The application 'rspec' is installed as part of a gem, and
|
8
|
-
# this file is here to facilitate running it.
|
9
|
-
#
|
10
|
-
|
11
|
-
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
-
Pathname.new(__FILE__).realpath)
|
14
|
-
|
15
|
-
bundle_binstub = File.expand_path('bundle', __dir__)
|
16
|
-
|
17
|
-
if File.file?(bundle_binstub)
|
18
|
-
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
-
load(bundle_binstub)
|
20
|
-
else
|
21
|
-
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
-
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
require "rubygems"
|
27
|
-
require "bundler/setup"
|
28
|
-
|
29
|
-
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'bundler/inline'
|
5
|
-
require 'bundler'
|
6
|
-
|
7
|
-
# We need the `Bundler.settings.temporary` for a bundler bug:
|
8
|
-
# https://github.com/bundler/bundler/issues/7114
|
9
|
-
# Will get fixed in bundler version 2.1.0
|
10
|
-
Bundler.settings.temporary(frozen: false) do
|
11
|
-
gemfile do
|
12
|
-
source 'https://rubygems.org'
|
13
|
-
gem 'rubocop', '~> 0.78.0'
|
14
|
-
gem 'relaxed-rubocop', '2.4'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
load Gem.bin_path("rubocop", "rubocop")
|
data/bin/setup
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Teckel
|
4
|
-
module Operation
|
5
|
-
# Works just like +Teckel::Operation+, but wraps +output+ and +error+ into a +Teckel::Result+.
|
6
|
-
#
|
7
|
-
# A +Teckel::Result+ given as +input+ will get unwrapped, so that the original +value+
|
8
|
-
# gets passed to your Operation code.
|
9
|
-
#
|
10
|
-
# @example
|
11
|
-
#
|
12
|
-
# class CreateUser
|
13
|
-
# include Teckel::Operation::Results
|
14
|
-
#
|
15
|
-
# input Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer)
|
16
|
-
# output Types.Instance(User)
|
17
|
-
# error Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))
|
18
|
-
#
|
19
|
-
# # @param [Hash<name: String, age: Integer>]
|
20
|
-
# # @return [User | Hash<message: String, errors: [Hash]>]
|
21
|
-
# def call(input)
|
22
|
-
# user = User.new(name: input[:name], age: input[:age])
|
23
|
-
# if user.safe
|
24
|
-
# # exits early with success, prevents any further execution
|
25
|
-
# success!(user)
|
26
|
-
# else
|
27
|
-
# fail!(message: "Could not safe User", errors: user.errors)
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# # A success call:
|
33
|
-
# CreateUser.call(name: "Bob", age: 23).is_a?(Teckel::Result) #=> true
|
34
|
-
# CreateUser.call(name: "Bob", age: 23).success.is_a?(User) #=> true
|
35
|
-
#
|
36
|
-
# # A failure call:
|
37
|
-
# CreateUser.call(name: "Bob", age: 10).is_a?(Teckel::Result) #=> true
|
38
|
-
# CreateUser.call(name: "Bob", age: 10).failure.is_a?(Hash) #=> true
|
39
|
-
#
|
40
|
-
# # Unwrapping success input:
|
41
|
-
# CreateUser.call(Teckel::Result.new({name: "Bob", age: 23}, true)).success.is_a?(User) #=> true
|
42
|
-
#
|
43
|
-
# # Unwrapping failure input:
|
44
|
-
# CreateUser.call(Teckel::Result.new({name: "Bob", age: 23}, false)).success.is_a?(User) #=> true
|
45
|
-
#
|
46
|
-
# @api public
|
47
|
-
module Results
|
48
|
-
module InstanceMethods
|
49
|
-
private
|
50
|
-
|
51
|
-
def build_input(input)
|
52
|
-
input = input.value if input.is_a?(Teckel::Result)
|
53
|
-
super(input)
|
54
|
-
end
|
55
|
-
|
56
|
-
def build_output(*args)
|
57
|
-
Teckel::Result.new(super, true)
|
58
|
-
end
|
59
|
-
|
60
|
-
def build_error(*args)
|
61
|
-
Teckel::Result.new(super, false)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.included(receiver)
|
66
|
-
receiver.send :include, Teckel::Operation unless Teckel::Operation >= receiver
|
67
|
-
receiver.send :include, InstanceMethods
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|