ree_lib 1.0.36 → 1.0.37

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -2
  3. data/lib/ree_lib/Packages.schema.json +8 -0
  4. data/lib/ree_lib/packages/ree_actions/.gitignore +0 -0
  5. data/lib/ree_lib/packages/ree_actions/.rspec +2 -0
  6. data/lib/ree_lib/packages/ree_actions/Package.schema.json +20 -0
  7. data/lib/ree_lib/packages/ree_actions/bin/console +5 -0
  8. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action.rb +10 -0
  9. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_builder.rb +65 -0
  10. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_dsl.rb +60 -0
  11. data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +102 -0
  12. data/lib/ree_lib/packages/ree_actions/package/ree_actions.rb +12 -0
  13. data/lib/ree_lib/packages/ree_actions/spec/package_schema_spec.rb +14 -0
  14. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/action_dsl_spec.rb +62 -0
  15. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +93 -0
  16. data/lib/ree_lib/packages/ree_actions/spec/spec_helper.rb +3 -0
  17. data/lib/ree_lib/packages/ree_roda/.gitignore +0 -0
  18. data/lib/ree_lib/packages/ree_roda/.rspec +2 -0
  19. data/lib/ree_lib/packages/ree_roda/Package.schema.json +58 -0
  20. data/lib/ree_lib/packages/ree_roda/bin/console +5 -0
  21. data/lib/ree_lib/packages/ree_roda/package/ree_roda/app.rb +46 -0
  22. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_actions.rb +150 -0
  23. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_logger.rb +66 -0
  24. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_action_errors.rb +76 -0
  25. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb +55 -0
  26. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/status_from_error.rb +25 -0
  27. data/lib/ree_lib/packages/ree_roda/package/ree_roda.rb +19 -0
  28. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json +28 -0
  29. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json +63 -0
  30. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json +28 -0
  31. data/lib/ree_lib/packages/ree_roda/spec/package_schema_spec.rb +14 -0
  32. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +84 -0
  33. data/lib/ree_lib/packages/ree_roda/spec/spec_helper.rb +3 -0
  34. data/lib/ree_lib/version.rb +1 -1
  35. metadata +60 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61b5c4cb5d7eef9fc932ebe3a674c5c752cb82d035248910a8a3da7a1ffe45b5
4
- data.tar.gz: d604e93726df4c19ebfe4c244a9d91da836e2a587d8599969bd9e5980a4e07d9
3
+ metadata.gz: bfa479493ff3b8d80a181db242e9f443324b5c7f46b3629dae816f06eb2fd758
4
+ data.tar.gz: 371e0a229e967c47f8ad61de6c86aba1bb0e0b17651bf6447e7727734629e294
5
5
  SHA512:
6
- metadata.gz: e05879958d07507dce29039623c4c88a5eb4b49ea7c9eee56b86346f004cbea2f455a42464142cc91d04aeefb07e65d3f2436073a3e58bcfd9434b6512cc8d31
7
- data.tar.gz: c5888ac8151e1016bde7705fdbdc13bc4f814007401ff23d9da9bac160810ca6e1b92008015b507e90a110035848189d6d291093b7fea42ca1df7d6c5f962c24
6
+ metadata.gz: 71b4a7f35d1a0569af42794acf8bf8c1193cf390ca773fd6ebab395cb86192199496812c9ae356e29a299a453304d6c25217cd20d9bd7884ded1e10fa798d68f
7
+ data.tar.gz: c5b3cf9ea44d8012ea7be12cf8ef9f33ac735a28c8d9bb384bf69fec6f8bc7932b7a1cf6f43be4439d7fa220b3cc2e630d8e0816b75c732fcb9b13e3e1b6ef22
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.36)
4
+ ree_lib (1.0.37)
5
5
  binding_of_caller (~> 1.0.0)
6
6
  i18n (~> 1.12.0)
7
7
  loofah (~> 2.18.0)
@@ -44,11 +44,16 @@ GEM
44
44
  pg (1.4.6)
45
45
  public_suffix (5.0.1)
46
46
  racc (1.6.2)
47
+ rack (3.0.5)
48
+ rack-test (2.0.2)
49
+ rack (>= 1.3)
47
50
  rainbow (3.1.1)
48
51
  rake (13.0.6)
49
- ree (1.0.26)
52
+ ree (1.0.27)
50
53
  commander (~> 4.6.0)
51
54
  rexml (3.2.5)
55
+ roda (3.58.0)
56
+ rack
52
57
  rollbar (3.3.3)
53
58
  rspec (3.12.0)
54
59
  rspec-core (~> 3.12.0)
@@ -81,8 +86,10 @@ PLATFORMS
81
86
  DEPENDENCIES
82
87
  bootsnap
83
88
  pg (~> 1.4.1)
89
+ rack-test
84
90
  rake (~> 13.0)
85
91
  ree_lib!
92
+ roda (~> 3.58.0)
86
93
  rollbar (~> 3.3.1)
87
94
  rspec
88
95
  sqlite3 (~> 1.4.4)
@@ -2,6 +2,10 @@
2
2
  "schema_version": "1.0",
3
3
  "schema_type": "packages",
4
4
  "packages": [
5
+ {
6
+ "name": "ree_actions",
7
+ "schema": "packages/ree_actions/Package.schema.json"
8
+ },
5
9
  {
6
10
  "name": "ree_array",
7
11
  "schema": "packages/ree_array/Package.schema.json"
@@ -66,6 +70,10 @@
66
70
  "name": "ree_object",
67
71
  "schema": "packages/ree_object/Package.schema.json"
68
72
  },
73
+ {
74
+ "name": "ree_roda",
75
+ "schema": "packages/ree_roda/Package.schema.json"
76
+ },
69
77
  {
70
78
  "name": "ree_string",
71
79
  "schema": "packages/ree_string/Package.schema.json"
File without changes
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,20 @@
1
+ {
2
+ "schema_type": "package",
3
+ "schema_version": "1.1",
4
+ "name": "ree_actions",
5
+ "entry_path": "packages/ree_actions/package/ree_actions.rb",
6
+ "tags": [
7
+ "ree_actions"
8
+ ],
9
+ "depends_on": [
10
+ {
11
+ "name": "ree_mapper"
12
+ }
13
+ ],
14
+ "env_vars": [
15
+
16
+ ],
17
+ "objects": [
18
+
19
+ ]
20
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "ree"
4
+
5
+ Ree.init(__dir__, irb: true)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ReeActions::Action
4
+ attr_accessor :summary, :request_method, :serializer, :respond_to,
5
+ :sections, :action, :warden_scope, :path
6
+
7
+ def valid?
8
+ !@action.nil? && !summary.nil? && !warden_scope.nil?
9
+ end
10
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "action"
4
+
5
+ class ReeActions::ActionBuilder
6
+ Redirect = Struct.new(:path, :code)
7
+
8
+ def initialize
9
+ @action = ReeActions::Action.new
10
+ @action.respond_to = :json
11
+ end
12
+
13
+ contract Symbol => Symbol
14
+ def warden_scope(scope)
15
+ @action.warden_scope = scope
16
+ end
17
+
18
+ contract Symbol => Symbol
19
+ def respond_to(v)
20
+ @action.respond_to = v
21
+ end
22
+
23
+ contract None => ReeActions::Action
24
+ def get_action
25
+ @action
26
+ end
27
+
28
+ contract Block => nil
29
+ def before(&proc)
30
+ @action.before = proc
31
+ nil
32
+ end
33
+
34
+ contract String => String
35
+ def summary(str)
36
+ @action.summary = str
37
+ end
38
+
39
+ contract Symbol, Symbol => nil
40
+ def serializer(name, from:)
41
+ object = Ree.container.packages_facade.get_object(from, name)
42
+ @action.serializer = object
43
+ nil
44
+ end
45
+
46
+ contract SplatOf[String] => nil
47
+ def sections(*names)
48
+ @action.sections = names
49
+ nil
50
+ end
51
+
52
+ contract Symbol, Symbol => nil
53
+ def action(name, from:)
54
+ object = Ree.container.packages_facade.get_object(from, name)
55
+ @action.action = object
56
+ nil
57
+ end
58
+
59
+ contract String, Kwargs[code: Integer] => nil
60
+ def redirect(path, code: 301)
61
+ raise ArgumentError if ![301, 302, 303, 307, 308].include?(code)
62
+ @action.redirect = Redirect.new(path, code)
63
+ nil
64
+ end
65
+ end
@@ -0,0 +1,60 @@
1
+ module ReeActions
2
+ module ActionDSL
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ base.include(ReeMapper::DSL)
6
+ end
7
+
8
+ def self.extended(base)
9
+ base.extend(ClassMethods)
10
+ base.include(ReeMapper::DSL)
11
+ end
12
+
13
+ module ClassMethods
14
+ include Ree::Contracts::Core
15
+ include Ree::Contracts::ArgContracts
16
+
17
+ def action(name, &proc)
18
+ dsl = Ree::ObjectDsl.new(
19
+ Ree.container.packages_facade, name, self, :fn
20
+ )
21
+
22
+ dsl.instance_exec(&proc) if block_given?
23
+ dsl.tags(["action"])
24
+ dsl.freeze(false)
25
+ dsl.object.set_as_compiled(false)
26
+
27
+ Ree.container.compile(dsl.package, name)
28
+ end
29
+
30
+ def method_added(method_name)
31
+ return super if method_name != :call
32
+
33
+ if @__original_call_defined
34
+ remove_instance_variable(:@__original_call_defined)
35
+ return
36
+ end
37
+
38
+ @__original_call_defined = true
39
+
40
+ alias_method(:__original_call, :call)
41
+
42
+ define_method :call do |user_access, attrs|
43
+ if self.class.const_defined?(:ActionCaster)
44
+ caster = self.class.const_get(:ActionCaster)
45
+
46
+ if !caster.respond_to?(:cast)
47
+ raise ArgumentError.new("ActionCaster does not respond to `cast` method")
48
+ end
49
+
50
+ __original_call(user_access, caster.cast(attrs))
51
+ else
52
+ __original_call(user_access, attrs)
53
+ end
54
+ end
55
+
56
+ nil
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "action_builder"
4
+ require "uri"
5
+
6
+ module ReeActions
7
+ module DSL
8
+ def self.included(base)
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ def self.extended(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+
16
+ module FactoryMethod
17
+ def build
18
+ self.class.instance_variable_get(:@actions) || []
19
+ end
20
+ end
21
+
22
+ module ClassMethods
23
+ include Ree::Contracts::Core
24
+ include Ree::Contracts::ArgContracts
25
+
26
+ def actions(name, &proc)
27
+ raise ArgumentError.new("block is required") if !block_given?
28
+
29
+ @dsl = Ree::ObjectDsl.new(
30
+ Ree.container.packages_facade, name, self, :object
31
+ )
32
+
33
+ @dsl.singleton
34
+ @dsl.factory(:build)
35
+ @dsl.tags(["actions"])
36
+
37
+ instance_exec(&proc)
38
+
39
+ klass = @dsl.object.klass
40
+ klass.send(:include, FactoryMethod)
41
+
42
+
43
+ Ree.container.compile(@dsl.package, name)
44
+ end
45
+
46
+ def default_warden_scope(method_name)
47
+ @default_warden_scope = method_name
48
+ end
49
+
50
+ [:get, :post, :put, :delete, :patch, :head, :options].each do |request_method|
51
+ define_method request_method do |path, &proc|
52
+ define_action(request_method, path, &proc)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ contract Symbol, String, Block => ReeActions::Action
59
+ def define_action(request_method, path, &proc)
60
+ raise ArgumentError.new("actions should be called") if !@dsl
61
+ raise ArgumentError.new("block is required") if !block_given?
62
+
63
+ @actions ||= []
64
+
65
+ builder = ReeActions::ActionBuilder.new
66
+ builder.instance_exec(&proc)
67
+
68
+ if @default_warden_scope && !builder.get_action.warden_scope
69
+ builder.warden_scope(@default_warden_scope)
70
+ end
71
+
72
+ uri = URI.parse(path) rescue nil
73
+
74
+ if uri.nil? || uri.path != path
75
+ raise ArgumentError.new("invalid path provided #{path}")
76
+ end
77
+
78
+ if uri.query && !uri.query.empty?
79
+ raise ArgumentError.new("action path should not include query params: #{path}")
80
+ end
81
+
82
+ builder.get_action.path = path
83
+ builder.get_action.request_method = request_method
84
+
85
+ if !builder.get_action.valid?
86
+ raise ArgumentError.new("action, summary and auth scope should be provider for #{builder.get_action.inspect}")
87
+ end
88
+
89
+ action = builder.get_action
90
+
91
+ @dsl.link(action.action.name, from: action.action.package_name)
92
+
93
+ if action.serializer
94
+ @dsl.link(action.serializer.name, from: action.serializer.package_name)
95
+ end
96
+
97
+ @actions << action
98
+ action
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReeActions
4
+ include Ree::PackageDSL
5
+
6
+ package do
7
+ depends_on :ree_mapper
8
+ end
9
+ end
10
+
11
+ require_relative "ree_actions/dsl"
12
+ require_relative "ree_actions/action_dsl"
@@ -0,0 +1,14 @@
1
+ RSpec.describe "ReeActions" do
2
+ it "generates package schema" do
3
+ require "fileutils"
4
+
5
+ packages_schema_path = Ree.locate_packages_schema(__dir__)
6
+ packages_schema_dir = Pathname.new(packages_schema_path).dirname.to_s
7
+
8
+ FileUtils.cd packages_schema_dir do
9
+ expect(
10
+ system("REE_SKIP_ENV_VARS_CHECK=true bundle exec ree gen.package_json ree_actions --silence")
11
+ ).to eq(true)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,62 @@
1
+ package_require("ree_actions/action_dsl")
2
+
3
+ RSpec.describe ReeActions::ActionDSL, type: [:autoclean] do
4
+ before do
5
+ Ree.enable_irb_mode
6
+ end
7
+
8
+ after do
9
+ Ree.disable_irb_mode
10
+ end
11
+
12
+ it {
13
+ module ReeActionsTest
14
+ include Ree::PackageDSL
15
+
16
+ package do
17
+ depends_on :ree_mapper
18
+ end
19
+
20
+ class TestAction
21
+ include ReeActions::ActionDSL
22
+
23
+ action :test_action
24
+
25
+ ActionCaster = build_mapper.use(:cast) do
26
+ integer :user_id
27
+ end
28
+
29
+ contract Any, ActionCaster.dto(:cast) => Integer
30
+ def call(user_access, attrs)
31
+ attrs[:user_id]
32
+ end
33
+ end
34
+ end
35
+
36
+ result = ReeActionsTest::TestAction.new.call('user_access', {user_id: 1})
37
+ expect(result).to eq(1)
38
+ }
39
+
40
+ it {
41
+ module ReeActionsTest
42
+ include Ree::PackageDSL
43
+
44
+ package do
45
+ end
46
+
47
+ class TestAction2
48
+ include ReeActions::ActionDSL
49
+
50
+ action :test_action2
51
+
52
+ contract Any, Hash => Integer
53
+ def call(user_access, attrs)
54
+ attrs[:user_id]
55
+ end
56
+ end
57
+ end
58
+
59
+ result = ReeActionsTest::TestAction2.new.call('user_access', {user_id: 1})
60
+ expect(result).to eq(1)
61
+ }
62
+ end
@@ -0,0 +1,93 @@
1
+ package_require("ree_actions/dsl")
2
+
3
+ RSpec.describe ReeActions::DSL, type: [:autoclean] do
4
+ before :all do
5
+ Ree.enable_irb_mode
6
+
7
+ module ReeActionsTest
8
+ include Ree::PackageDSL
9
+
10
+ package
11
+ end
12
+
13
+ class ReeActionsTest::EmptyActions
14
+ include ReeActions::DSL
15
+
16
+ actions :empty_actions do
17
+ end
18
+ end
19
+
20
+ class ReeActionsTest::Cmd
21
+ include Ree::FnDSL
22
+
23
+ fn :cmd
24
+
25
+ def call
26
+ end
27
+ end
28
+
29
+ class ReeActionsTest::Serializer
30
+ include ReeMapper::DSL
31
+
32
+ mapper :serializer
33
+
34
+ build_mapper.use(:serialize) do
35
+ integer :id
36
+ end
37
+ end
38
+
39
+ class ReeActionsTest::Caster
40
+ include ReeMapper::DSL
41
+
42
+ mapper :caster
43
+
44
+ build_mapper.use(:cast) do
45
+ integer :id
46
+ end
47
+ end
48
+
49
+ class ReeActionsTest::Actions
50
+ include ReeActions::DSL
51
+
52
+ actions :actions do
53
+ default_warden_scope :user
54
+
55
+ post "users" do
56
+ summary "Test action"
57
+ action :cmd, from: :ree_actions_test
58
+ serializer :serializer, from: :ree_actions_test
59
+ respond_to :json
60
+ end
61
+
62
+ get "files.csv" do
63
+ summary "Test action"
64
+ action :cmd, from: :ree_actions_test
65
+ respond_to :csv
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ after :all do
72
+ Ree.disable_irb_mode
73
+ end
74
+
75
+ it {
76
+ expect(ReeActionsTest::EmptyActions.new).to eq([])
77
+ }
78
+
79
+ it {
80
+ actions = ReeActionsTest::Actions.new
81
+
82
+ expect(actions.size).to eq(2)
83
+
84
+ post_action = actions.first
85
+ csv_action = actions.last
86
+
87
+ expect(post_action.serializer.name).to eq(:serializer)
88
+ expect(post_action.action.name).to eq(:cmd)
89
+ expect(post_action.respond_to).to eq(:json)
90
+
91
+ expect(csv_action.respond_to).to eq(:csv)
92
+ }
93
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.extend Ree::RSpecLinkDSL
3
+ end
File without changes
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,58 @@
1
+ {
2
+ "schema_type": "package",
3
+ "schema_version": "1.1",
4
+ "name": "ree_roda",
5
+ "entry_path": "packages/ree_roda/package/ree_roda.rb",
6
+ "tags": [
7
+ "ree_roda"
8
+ ],
9
+ "depends_on": [
10
+ {
11
+ "name": "ree_actions"
12
+ },
13
+ {
14
+ "name": "ree_errors"
15
+ },
16
+ {
17
+ "name": "ree_hash"
18
+ },
19
+ {
20
+ "name": "ree_json"
21
+ },
22
+ {
23
+ "name": "ree_logger"
24
+ },
25
+ {
26
+ "name": "ree_object"
27
+ },
28
+ {
29
+ "name": "ree_swagger"
30
+ }
31
+ ],
32
+ "env_vars": [
33
+
34
+ ],
35
+ "objects": [
36
+ {
37
+ "name": "build_action_errors",
38
+ "schema": "packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json",
39
+ "tags": [
40
+ "fn"
41
+ ]
42
+ },
43
+ {
44
+ "name": "build_swagger_from_actions",
45
+ "schema": "packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json",
46
+ "tags": [
47
+ "fn"
48
+ ]
49
+ },
50
+ {
51
+ "name": "status_from_error",
52
+ "schema": "packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json",
53
+ "tags": [
54
+ "fn"
55
+ ]
56
+ }
57
+ ]
58
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require "bundler/setup"
3
+ require "ree"
4
+
5
+ Ree.init(__dir__, irb: true)
@@ -0,0 +1,46 @@
1
+ package_require("ree_errors/error")
2
+ package_require("ree_mapper/errors/type_error")
3
+
4
+ class ReeRoda::App < Roda
5
+ include Ree::LinkDSL
6
+
7
+ link :logger, from: :ree_logger
8
+ link :status_from_error
9
+ link :to_json, from: :ree_json
10
+
11
+ plugin :error_handler
12
+ plugin :json_parser
13
+ plugin :type_routing, default_type: :json
14
+
15
+ error do |e|
16
+ response["Content-Type"] = "application/json"
17
+
18
+ if e.is_a?(ReeErrors::Error)
19
+ body = {
20
+ code: e.code,
21
+ message: e.message,
22
+ type: e.type,
23
+ }
24
+
25
+ response.status = status_from_error(e.type)
26
+ response.write(to_json(body))
27
+ response.finish
28
+ elsif e.is_a?(ReeMapper::TypeError) || e.is_a?(ReeMapper::CoercionError)
29
+ body = {
30
+ code: "param",
31
+ message: e.message,
32
+ type: :invalid_param,
33
+ }
34
+
35
+ response.status = 400
36
+ response.write(to_json(body))
37
+ response.finish
38
+ else
39
+ logger.error(e.message, {}, e)
40
+ response["Content-Type"] = "text/plain"
41
+ response.status = 500
42
+ response.write("unhandled server error")
43
+ response.finish
44
+ end
45
+ end
46
+ end