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.
- checksums.yaml +7 -0
- data/CHANGES.md +3 -0
- data/Gemfile +16 -0
- data/README.md +11 -0
- data/Rakefile +10 -0
- data/lib/trailblazer-endpoint.rb +1 -0
- data/lib/trailblazer/endpoint.rb +133 -0
- data/lib/trailblazer/endpoint/adapter.rb +197 -0
- data/lib/trailblazer/endpoint/builder.rb +56 -0
- data/lib/trailblazer/endpoint/protocol.rb +122 -0
- data/lib/trailblazer/endpoint/rails.rb +27 -0
- data/lib/trailblazer/endpoint/version.rb +5 -0
- data/test/adapter/api_test.rb +78 -0
- data/test/adapter/representable_test.rb +7 -0
- data/test/adapter/web_test.rb +40 -0
- data/test/benchmark/skill_resolver_benchmark.rb +43 -0
- data/test/docs/controller_test.rb +92 -0
- data/test/docs/endpoint_test.rb +54 -0
- data/test/endpoint_test.rb +908 -0
- data/test/rails-app/.gitignore +21 -0
- data/test/rails-app/Gemfile +17 -0
- data/test/rails-app/Gemfile.lock +157 -0
- data/test/rails-app/README.md +24 -0
- data/test/rails-app/Rakefile +6 -0
- data/test/rails-app/app/controllers/application_controller.rb +3 -0
- data/test/rails-app/app/controllers/songs_controller.rb +26 -0
- data/test/rails-app/app/models/application_record.rb +3 -0
- data/test/rails-app/app/models/concerns/.keep +0 -0
- data/test/rails-app/config.ru +5 -0
- data/test/rails-app/config/application.rb +15 -0
- data/test/rails-app/config/boot.rb +3 -0
- data/test/rails-app/config/database.yml +25 -0
- data/test/rails-app/config/environment.rb +5 -0
- data/test/rails-app/config/environments/development.rb +54 -0
- data/test/rails-app/config/environments/production.rb +86 -0
- data/test/rails-app/config/environments/test.rb +42 -0
- data/test/rails-app/config/initializers/application_controller_renderer.rb +6 -0
- data/test/rails-app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails-app/config/initializers/cookies_serializer.rb +5 -0
- data/test/rails-app/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/rails-app/config/initializers/inflections.rb +16 -0
- data/test/rails-app/config/initializers/mime_types.rb +4 -0
- data/test/rails-app/config/initializers/new_framework_defaults.rb +24 -0
- data/test/rails-app/config/initializers/session_store.rb +3 -0
- data/test/rails-app/config/initializers/wrap_parameters.rb +14 -0
- data/test/rails-app/config/locales/en.yml +23 -0
- data/test/rails-app/config/routes.rb +6 -0
- data/test/rails-app/config/secrets.yml +22 -0
- data/test/rails-app/db/seeds.rb +7 -0
- data/test/rails-app/log/.keep +0 -0
- data/test/rails-app/test/controllers/.keep +0 -0
- data/test/rails-app/test/controllers/songs_controller_test.rb +156 -0
- data/test/rails-app/test/fixtures/.keep +0 -0
- data/test/rails-app/test/fixtures/files/.keep +0 -0
- data/test/rails-app/test/helpers/.keep +0 -0
- data/test/rails-app/test/integration/.keep +0 -0
- data/test/rails-app/test/mailers/.keep +0 -0
- data/test/rails-app/test/models/.keep +0 -0
- data/test/rails-app/test/test_helper.rb +10 -0
- data/test/rails-app/tmp/.keep +0 -0
- data/test/rails-app/vendor/assets/javascripts/.keep +0 -0
- data/test/rails-app/vendor/assets/stylesheets/.keep +0 -0
- data/test/test_helper.rb +34 -0
- data/trailblazer-endpoint.gemspec +26 -0
- 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,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,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,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,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
|
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
|
File without changes
|
File without changes
|
data/test/test_helper.rb
ADDED
@@ -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
|