rack-spec 0.0.5 → 0.1.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.
@@ -1,15 +0,0 @@
1
- module Rack
2
- class Spec
3
- class ExceptionHandler
4
- def initialize(app)
5
- @app = app
6
- end
7
-
8
- def call(env)
9
- @app.call(env)
10
- rescue Exceptions::ValidationError => exception
11
- exception.to_rack_response
12
- end
13
- end
14
- end
15
- end
@@ -1,8 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Exceptions
4
- class Base < StandardError
5
- end
6
- end
7
- end
8
- end
@@ -1,43 +0,0 @@
1
- require "json"
2
-
3
- module Rack
4
- class Spec
5
- module Exceptions
6
- class ValidationError < Base
7
- def initialize(validator)
8
- @validator = validator
9
- end
10
-
11
- def message
12
- "Invalid #{key} on `#{constraint_name}` constraint"
13
- end
14
-
15
- def to_rack_response
16
- [status, header, body]
17
- end
18
-
19
- private
20
-
21
- def constraint_name
22
- @validator.class.registered_name
23
- end
24
-
25
- def key
26
- @validator.key
27
- end
28
-
29
- def status
30
- 400
31
- end
32
-
33
- def header
34
- { "Content-Type" => "application/json" }
35
- end
36
-
37
- def body
38
- { message: message }.to_json
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,95 +0,0 @@
1
- require "active_support/core_ext/object/try"
2
- require "active_support/core_ext/string/inflections"
3
-
4
- module Rack
5
- class Spec
6
- class Restful
7
- def initialize(app, options = {})
8
- @app = app
9
- @options = options
10
- end
11
-
12
- def call(env)
13
- Proxy.new(@app, spec, env).call
14
- end
15
-
16
- private
17
-
18
- def spec
19
- Spec.new(@options[:spec])
20
- end
21
-
22
- class Proxy
23
- def initialize(app, spec, env)
24
- @app = app
25
- @spec = spec
26
- @env = env
27
- end
28
-
29
- def call
30
- if endpoint
31
- response = handler_class.send(handler_method_name, params)
32
- [
33
- response.try(:status) || default_status,
34
- default_header.merge(response.try(:header) || {}),
35
- [(response.try(:body) || response).to_json]
36
- ]
37
- else
38
- @app.call(@env)
39
- end
40
- end
41
-
42
- private
43
-
44
- def endpoint
45
- @endpoint ||= @spec.find_endpoint(@env)
46
- end
47
-
48
- def handler_class
49
- path_segments[1].singularize.camelize.constantize
50
- end
51
-
52
- def id
53
- path_segments[2]
54
- end
55
-
56
- def path_segments
57
- @path_segments ||= path.split("/")
58
- end
59
-
60
- def handler_method_name
61
- request_method.downcase
62
- end
63
-
64
- def path
65
- request.path
66
- end
67
-
68
- def request
69
- @env["rack-spec.request"] ||= Rack::Request.new(@env)
70
- end
71
-
72
- def request_method
73
- @env["REQUEST_METHOD"]
74
- end
75
-
76
- def params
77
- request.params.merge(@env["rack-spec.uri_parameters"])
78
- end
79
-
80
- def default_status
81
- {
82
- "GET" => 200,
83
- "POST" => 201,
84
- "PUT" => 204,
85
- "DELETE" => 204,
86
- }[request_method]
87
- end
88
-
89
- def default_header
90
- { "Content-tYpe" => "application/json" }
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,30 +0,0 @@
1
- require "addressable/template"
2
-
3
- module Rack
4
- class Spec
5
- class Spec < Hash
6
- def initialize(hash)
7
- hash.each do |key, value|
8
- self[key] = value
9
- end
10
- end
11
-
12
- def find_endpoint(env)
13
- self["endpoints"].find do |path, source|
14
- if parameters = Addressable::Template.new(path).extract(env["PATH_INFO"])
15
- if endpoint = source[env["REQUEST_METHOD"]]
16
- env["rack-spec.uri_parameters"] = parameters
17
- break endpoint
18
- end
19
- end
20
- end
21
- end
22
-
23
- def reach(*keys)
24
- keys.inject(self) do |hash, key|
25
- hash[key] if hash.respond_to?(:[])
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,21 +0,0 @@
1
- module Rack
2
- class Spec
3
- class Validation
4
- def initialize(app, options = {})
5
- @app = app
6
- @options = options
7
- end
8
-
9
- def call(env)
10
- Validators::ParametersValidator.new(spec, env).validate!
11
- @app.call(env)
12
- end
13
-
14
- private
15
-
16
- def spec
17
- Spec.new(@options[:spec])
18
- end
19
- end
20
- end
21
- end
@@ -1,19 +0,0 @@
1
- module Rack
2
- class Spec
3
- class ValidatorFactory
4
- class << self
5
- def validator_classes
6
- @validator_classes ||= Hash.new(Validators::NullValidator)
7
- end
8
-
9
- def register(name, klass)
10
- validator_classes[name] = klass
11
- end
12
-
13
- def build(key, type, constraint, env)
14
- validator_classes[type].new(key, constraint, env)
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,44 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class Base
5
- class << self
6
- attr_accessor :registered_name
7
-
8
- def register_as(name)
9
- self.registered_name = name
10
- ValidatorFactory.register(name, self)
11
- end
12
- end
13
-
14
- attr_reader :constraint, :key, :env
15
-
16
- def initialize(key, constraint, env)
17
- @key = key
18
- @constraint = constraint
19
- @env = env
20
- end
21
-
22
- def validate!
23
- unless valid?
24
- raise Exceptions::ValidationError, self
25
- end
26
- end
27
-
28
- def valid?
29
- raise NotImplementedError
30
- end
31
-
32
- private
33
-
34
- def value
35
- @value ||= request.params[@key]
36
- end
37
-
38
- def request
39
- env["rack-spec.request"] ||= Rack::Request.new(env)
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,13 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class MaximumLengthValidator < Base
5
- register_as "maximumLength"
6
-
7
- def valid?
8
- value.nil? || value.length <= constraint
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class MaximumValidator < Base
5
- register_as "maximum"
6
-
7
- def valid?
8
- value.nil? || value.to_f <= constraint
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class MinimumLengthValidator < Base
5
- register_as "minimumLength"
6
-
7
- def valid?
8
- value.nil? || value.length >= constraint
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class MinimumValidator < Base
5
- register_as "minimum"
6
-
7
- def valid?
8
- value.nil? || value.to_f >= constraint
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class NullValidator < Base
5
- def valid?
6
- true
7
- end
8
- end
9
- end
10
- end
11
- end
@@ -1,13 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class OnlyValidator < Base
5
- register_as "only"
6
-
7
- def valid?
8
- value.nil? || constraint.include?(value)
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,26 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class ParametersValidator
5
- def initialize(spec, env)
6
- @spec = spec
7
- @env = env
8
- end
9
-
10
- def validate!
11
- parameters.each do |key, hash|
12
- hash.each do |type, constraint|
13
- ValidatorFactory.build(key, type, constraint, @env).validate!
14
- end
15
- end
16
- end
17
-
18
- private
19
-
20
- def parameters
21
- @spec.find_endpoint(@env).try(:[], "parameters") || []
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,13 +0,0 @@
1
- module Rack
2
- class Spec
3
- module Validators
4
- class RequiredValidator < Base
5
- register_as "required"
6
-
7
- def valid?
8
- value.nil? == !constraint
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,36 +0,0 @@
1
- require "time"
2
-
3
- module Rack
4
- class Spec
5
- module Validators
6
- class TypeValidator < Base
7
- class << self
8
- def patterns
9
- @patterns ||= Hash.new(//)
10
- end
11
-
12
- def pattern(name, pattern)
13
- patterns[name] = pattern
14
- end
15
- end
16
-
17
- register_as "type"
18
-
19
- pattern "boolean", /\A(?:true|false)\z/
20
- pattern "float", /\A-?\d+(?:\.\d+)*\z/
21
- pattern "integer", /\A-?\d+\z/
22
- pattern "iso8601", ->(value) { Time.iso8601(value) rescue false }
23
-
24
- def valid?
25
- value.nil? || pattern === value
26
- end
27
-
28
- private
29
-
30
- def pattern
31
- self.class.patterns[constraint]
32
- end
33
- end
34
- end
35
- end
36
- end