trailblazer-endpoint 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.md +3 -0
  3. data/Gemfile +16 -0
  4. data/README.md +11 -0
  5. data/Rakefile +10 -0
  6. data/lib/trailblazer-endpoint.rb +1 -0
  7. data/lib/trailblazer/endpoint.rb +133 -0
  8. data/lib/trailblazer/endpoint/adapter.rb +197 -0
  9. data/lib/trailblazer/endpoint/builder.rb +56 -0
  10. data/lib/trailblazer/endpoint/protocol.rb +122 -0
  11. data/lib/trailblazer/endpoint/rails.rb +27 -0
  12. data/lib/trailblazer/endpoint/version.rb +5 -0
  13. data/test/adapter/api_test.rb +78 -0
  14. data/test/adapter/representable_test.rb +7 -0
  15. data/test/adapter/web_test.rb +40 -0
  16. data/test/benchmark/skill_resolver_benchmark.rb +43 -0
  17. data/test/docs/controller_test.rb +92 -0
  18. data/test/docs/endpoint_test.rb +54 -0
  19. data/test/endpoint_test.rb +908 -0
  20. data/test/rails-app/.gitignore +21 -0
  21. data/test/rails-app/Gemfile +17 -0
  22. data/test/rails-app/Gemfile.lock +157 -0
  23. data/test/rails-app/README.md +24 -0
  24. data/test/rails-app/Rakefile +6 -0
  25. data/test/rails-app/app/controllers/application_controller.rb +3 -0
  26. data/test/rails-app/app/controllers/songs_controller.rb +26 -0
  27. data/test/rails-app/app/models/application_record.rb +3 -0
  28. data/test/rails-app/app/models/concerns/.keep +0 -0
  29. data/test/rails-app/config.ru +5 -0
  30. data/test/rails-app/config/application.rb +15 -0
  31. data/test/rails-app/config/boot.rb +3 -0
  32. data/test/rails-app/config/database.yml +25 -0
  33. data/test/rails-app/config/environment.rb +5 -0
  34. data/test/rails-app/config/environments/development.rb +54 -0
  35. data/test/rails-app/config/environments/production.rb +86 -0
  36. data/test/rails-app/config/environments/test.rb +42 -0
  37. data/test/rails-app/config/initializers/application_controller_renderer.rb +6 -0
  38. data/test/rails-app/config/initializers/backtrace_silencers.rb +7 -0
  39. data/test/rails-app/config/initializers/cookies_serializer.rb +5 -0
  40. data/test/rails-app/config/initializers/filter_parameter_logging.rb +4 -0
  41. data/test/rails-app/config/initializers/inflections.rb +16 -0
  42. data/test/rails-app/config/initializers/mime_types.rb +4 -0
  43. data/test/rails-app/config/initializers/new_framework_defaults.rb +24 -0
  44. data/test/rails-app/config/initializers/session_store.rb +3 -0
  45. data/test/rails-app/config/initializers/wrap_parameters.rb +14 -0
  46. data/test/rails-app/config/locales/en.yml +23 -0
  47. data/test/rails-app/config/routes.rb +6 -0
  48. data/test/rails-app/config/secrets.yml +22 -0
  49. data/test/rails-app/db/seeds.rb +7 -0
  50. data/test/rails-app/log/.keep +0 -0
  51. data/test/rails-app/test/controllers/.keep +0 -0
  52. data/test/rails-app/test/controllers/songs_controller_test.rb +156 -0
  53. data/test/rails-app/test/fixtures/.keep +0 -0
  54. data/test/rails-app/test/fixtures/files/.keep +0 -0
  55. data/test/rails-app/test/helpers/.keep +0 -0
  56. data/test/rails-app/test/integration/.keep +0 -0
  57. data/test/rails-app/test/mailers/.keep +0 -0
  58. data/test/rails-app/test/models/.keep +0 -0
  59. data/test/rails-app/test/test_helper.rb +10 -0
  60. data/test/rails-app/tmp/.keep +0 -0
  61. data/test/rails-app/vendor/assets/javascripts/.keep +0 -0
  62. data/test/rails-app/vendor/assets/stylesheets/.keep +0 -0
  63. data/test/test_helper.rb +34 -0
  64. data/trailblazer-endpoint.gemspec +26 -0
  65. metadata +236 -0
@@ -0,0 +1,42 @@
1
+ Rails.application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb.
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Do not eager load code on boot. This avoids loading your whole application
11
+ # just for the purpose of running a single test. If you are using a tool that
12
+ # preloads Rails for running tests, you may have to set it to true.
13
+ config.eager_load = false
14
+
15
+ # Configure public file server for tests with Cache-Control for performance.
16
+ config.public_file_server.enabled = true
17
+ config.public_file_server.headers = {
18
+ 'Cache-Control' => 'public, max-age=3600'
19
+ }
20
+
21
+ # Show full error reports and disable caching.
22
+ config.consider_all_requests_local = true
23
+ config.action_controller.perform_caching = false
24
+
25
+ # Raise exceptions instead of rendering exception templates.
26
+ config.action_dispatch.show_exceptions = false
27
+
28
+ # Disable request forgery protection in test environment.
29
+ config.action_controller.allow_forgery_protection = false
30
+ config.action_mailer.perform_caching = false
31
+
32
+ # Tell Action Mailer not to deliver emails to the real world.
33
+ # The :test delivery method accumulates sent emails in the
34
+ # ActionMailer::Base.deliveries array.
35
+ config.action_mailer.delivery_method = :test
36
+
37
+ # Print deprecation notices to the stderr.
38
+ config.active_support.deprecation = :stderr
39
+
40
+ # Raises error for missing translations
41
+ # config.action_view.raise_on_missing_translations = true
42
+ end
@@ -0,0 +1,6 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # ApplicationController.renderer.defaults.merge!(
4
+ # http_host: 'example.org',
5
+ # https: false
6
+ # )
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4
+ # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5
+
6
+ # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7
+ # Rails.backtrace_cleaner.remove_silencers!
@@ -0,0 +1,5 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Specify a serializer for the signed and encrypted cookie jars.
4
+ # Valid options are :json, :marshal, and :hybrid.
5
+ Rails.application.config.action_dispatch.cookies_serializer = :json
@@ -0,0 +1,4 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Configure sensitive parameters which will be filtered from the log file.
4
+ Rails.application.config.filter_parameters += [:password]
@@ -0,0 +1,16 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new inflection rules using the following format. Inflections
4
+ # are locale specific, and you may define rules for as many different
5
+ # locales as you wish. All of these examples are active by default:
6
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
7
+ # inflect.plural /^(ox)$/i, '\1en'
8
+ # inflect.singular /^(ox)en/i, '\1'
9
+ # inflect.irregular 'person', 'people'
10
+ # inflect.uncountable %w( fish sheep )
11
+ # end
12
+
13
+ # These inflection rules are supported but not enabled by default:
14
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
15
+ # inflect.acronym 'RESTful'
16
+ # end
@@ -0,0 +1,4 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new mime types for use in respond_to blocks:
4
+ # Mime::Type.register "text/richtext", :rtf
@@ -0,0 +1,24 @@
1
+ # Be sure to restart your server when you modify this file.
2
+ #
3
+ # This file contains migration options to ease your Rails 5.0 upgrade.
4
+ #
5
+ # Read the Rails 5.0 release notes for more info on each option.
6
+
7
+ # Enable per-form CSRF tokens. Previous versions had false.
8
+ Rails.application.config.action_controller.per_form_csrf_tokens = true
9
+
10
+ # Enable origin-checking CSRF mitigation. Previous versions had false.
11
+ Rails.application.config.action_controller.forgery_protection_origin_check = true
12
+
13
+ # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
14
+ # Previous versions had false.
15
+ ActiveSupport.to_time_preserves_timezone = true
16
+
17
+ # Require `belongs_to` associations by default. Previous versions had false.
18
+ Rails.application.config.active_record.belongs_to_required_by_default = true
19
+
20
+ # Do not halt callback chains when a callback returns false. Previous versions had true.
21
+ ActiveSupport.halt_callback_chains_on_return_false = false
22
+
23
+ # Configure SSL options to enable HSTS with subdomains. Previous versions had false.
24
+ Rails.application.config.ssl_options = { hsts: { subdomains: true } }
@@ -0,0 +1,3 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Rails.application.config.session_store :cookie_store, key: '_rails-app_session'
@@ -0,0 +1,14 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # This file contains settings for ActionController::ParamsWrapper which
4
+ # is enabled by default.
5
+
6
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
+ ActiveSupport.on_load(:action_controller) do
8
+ wrap_parameters format: [:json]
9
+ end
10
+
11
+ # To enable root element in JSON for ActiveRecord objects.
12
+ # ActiveSupport.on_load(:active_record) do
13
+ # self.include_root_in_json = true
14
+ # end
@@ -0,0 +1,23 @@
1
+ # Files in the config/locales directory are used for internationalization
2
+ # and are automatically loaded by Rails. If you want to use locales other
3
+ # than English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t 'hello'
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t('hello') %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # To learn more, please read the Rails Internationalization guide
20
+ # available at http://guides.rubyonrails.org/i18n.html.
21
+
22
+ en:
23
+ hello: "Hello world"
@@ -0,0 +1,6 @@
1
+ Rails.application.routes.draw do
2
+ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
3
+ resources :songs
4
+ post "update_with_user", to: "songs#update_with_user"
5
+ post "create_with_custom_handlers", to: "songs#create_with_custom_handlers"
6
+ end
@@ -0,0 +1,22 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key is used for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+
6
+ # Make sure the secret is at least 30 characters and all random,
7
+ # no regular words or you'll be exposed to dictionary attacks.
8
+ # You can use `rails secret` to generate a secure secret key.
9
+
10
+ # Make sure the secrets in this file are kept private
11
+ # if you're sharing your code publicly.
12
+
13
+ development:
14
+ secret_key_base: 1b32956d5c4b81c91b20acbc5f1b3e13874e0c6617eaab7fc582aac62c7aa64680eade373d83118e2fdc248ab2b226d3bfc549286c709c4f34f31d0c4ca6fea0
15
+
16
+ test:
17
+ secret_key_base: 0482c39f2747ee5844978ec66786934a2486c8fbc10ef3e6c7f7a148baf255918fb07ff5752d0d189eeb644b9c76164d25b17df33fea38f24a4eae529a5f16a0
18
+
19
+ # Do not keep production secrets in the repository,
20
+ # instead read values from the environment.
21
+ production:
22
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
@@ -0,0 +1,7 @@
1
+ # This file should contain all the record creation needed to seed the database with its default values.
2
+ # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3
+ #
4
+ # Examples:
5
+ #
6
+ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7
+ # Character.create(name: 'Luke', movie: movies.first)
File without changes
File without changes
@@ -0,0 +1,156 @@
1
+ require "test_helper"
2
+
3
+ module Reform
4
+ Form = nil
5
+ end # FIXME
6
+
7
+
8
+ Song = Struct.new(:id, :title, :length) do
9
+ def self.find_by(id:1); id=="0" ? nil : new(id, "A Song") end
10
+ end
11
+
12
+ require "trailblazer"
13
+ require "trailblazer/operation/model"
14
+ # require "reform/form/active_model/validations"
15
+ require "trailblazer/operation/contract"
16
+ require "trailblazer/operation/representer"
17
+ require "trailblazer/operation/guard"
18
+ require "trailblazer/endpoint"
19
+
20
+
21
+ require "representable/json"
22
+ class Serializer < Representable::Decorator
23
+ include Representable::JSON
24
+ property :id
25
+ property :title
26
+ property :length
27
+
28
+ class Errors < Representable::Decorator
29
+ include Representable::JSON
30
+ property :messages
31
+ end
32
+ end
33
+
34
+ class Deserializer < Representable::Decorator
35
+ include Representable::JSON
36
+ property :title
37
+ end
38
+
39
+
40
+ class Create < Trailblazer::Operation
41
+ include Policy::Guard
42
+ policy ->(*) { self["user.current"] == ::Module }
43
+
44
+ extend Representer::DSL
45
+ representer :serializer, Serializer
46
+ representer :deserializer, Deserializer
47
+ representer :errors, Serializer::Errors
48
+ # self["representer.serializer.class"] = Representer
49
+ # self["representer.deserializer.class"] = Deserializer
50
+
51
+ include Model
52
+ model Song, :create
53
+
54
+ include Contract::Step
55
+ include Representer::Deserializer::JSON
56
+ # contract do
57
+ # property :title
58
+ # property :length
59
+
60
+ # include Reform::Form::ActiveModel::Validations
61
+ # validates :title, presence: true
62
+ # end
63
+
64
+ # FIXME: use trb-rails and reform
65
+ class FakeContract
66
+ def initialize(model,*); @model = model end
67
+ def call(params)
68
+ if params[:title]
69
+ @title, @length = params[:title],params[:length]
70
+ return Trailblazer::Operation::Result.new(true, {})
71
+ end
72
+
73
+ return Struct.new(:errors, :success?).new(Struct.new(:messages).new({"title": ["must be set"]}), false)
74
+ end
75
+ def sync; @model.title = @title; @model.length = @length; end
76
+ end
77
+
78
+ contract FakeContract
79
+
80
+ def process(params)
81
+ validate(params) do |f|
82
+ self["contract"].sync
83
+ self["model"].id = 9
84
+ end
85
+ end
86
+ end
87
+
88
+ class Update < Create
89
+ action :find_by
90
+ end
91
+
92
+ # TODO: test present.
93
+ class Show < Trailblazer::Operation
94
+ include Policy::Guard
95
+ policy ->(*) { self["user.current"] == ::Module }
96
+
97
+ extend Representer::DSL
98
+ representer :serializer, Serializer
99
+
100
+ include Model
101
+ model Song, :find_by
102
+
103
+ self.> ->(input, options) { options["present"] = true }, before: "operation.result"
104
+ end
105
+
106
+ class SongsControllerTest < ActionController::TestCase
107
+ # 404
108
+ test "update 404" do
109
+ post :update, params: { id: 0 }
110
+ assert_equal 404, response.status
111
+ end
112
+
113
+ # 401
114
+ test "update 401" do
115
+ post :update, params: { id: 1 }
116
+ assert_equal 401, response.status
117
+ end
118
+
119
+ # 422
120
+ # TODO: test when no error repr set.
121
+ test "update 422" do
122
+ post :create, params: { id: 1 }
123
+ assert_equal 422, response.status
124
+ assert_equal %{{\"messages\":{\"title\":[\"must be set\"]}}}, response.body
125
+ end
126
+
127
+ # 201
128
+ test "create 201" do
129
+ post :create, params: { id: 1, title: "AVH" }
130
+ assert_equal 201, response.status
131
+ assert_equal %{}, response.body
132
+ assert_equal "/songs/9", response.header["Location"]
133
+ end
134
+
135
+ # 200 present
136
+ test "show 200" do
137
+ get :show, params: { id: 1 }
138
+ assert_equal 200, response.status
139
+ assert_equal %{{"id":"1","title":"A Song"}}, response.body
140
+ end
141
+
142
+ # 201 update
143
+ test "update 200" do
144
+ post :update_with_user, params: { id: 1, title: "AVH" }
145
+ assert_equal 200, response.status
146
+ assert_equal %{}, response.body
147
+ assert_equal "/songs/9", response.header["Location"]
148
+ end
149
+
150
+ # custom 999
151
+ test "custom 999" do
152
+ post :create_with_custom_handlers, params: { id: 1, title: "AVH" }
153
+ assert_equal 999, response.status
154
+ assert_equal %{{"id":9,"title":"AVH"}}, response.body
155
+ end
156
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,10 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rails/test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
7
+ fixtures :all
8
+
9
+ # Add more helper methods to be used by all tests here...
10
+ end
File without changes
@@ -0,0 +1,34 @@
1
+ require "minitest/autorun"
2
+ require "trailblazer/activity/dsl/linear"
3
+ require "trailblazer/activity/testing"
4
+ require "trailblazer/developer"
5
+
6
+ require "trailblazer/endpoint"
7
+ require "trailblazer/endpoint/protocol"
8
+ require "trailblazer/endpoint/adapter"
9
+
10
+ require "test_helper"
11
+
12
+ Minitest::Spec.class_eval do
13
+ T = Trailblazer::Activity::Testing
14
+
15
+ def assert_route(endpoint, ctx_additions, *route, **ctx_assumptions)
16
+ seq = route[0..-2]
17
+ terminus = route[-1]
18
+
19
+ signal, (ctx, ) = Trailblazer::Developer.wtf?(endpoint, [{seq: [], domain_ctx: {}}.merge(ctx_additions)])
20
+ signal.inspect.must_equal %{#<Trailblazer::Activity::End semantic=#{terminus.inspect}>}
21
+ ctx[:seq].must_equal seq
22
+
23
+ ctx.to_h.slice(*ctx_assumptions.keys).must_equal ctx_assumptions
24
+ end
25
+
26
+ def activity
27
+ activity = Class.new(Trailblazer::Activity::Railway) do
28
+ step :model, Output(:failure) => End(:not_found)
29
+ step :validate
30
+
31
+ include T.def_steps(:validate, :model)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'trailblazer/endpoint/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "trailblazer-endpoint"
7
+ spec.version = Trailblazer::Endpoint::VERSION
8
+ spec.authors = ["Nick Sutterer"]
9
+ spec.email = ["apotonick@gmail.com"]
10
+ spec.description = %q{Endpoints handle authentication, policies, run your domain operation and set up the rendering.}
11
+ spec.summary = %q{Endpoints handle authentication, policies, run your domain operation and set up the rendering.}
12
+ spec.homepage = "http://trailblazer.to/gems/operation/endpoint.html"
13
+ spec.license = "LGPL-3.0"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.2.9", "< 0.4.0"
21
+
22
+ spec.add_development_dependency "bundler"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "minitest"
25
+ spec.add_development_dependency "trailblazer-developer"
26
+ end