useless-doc 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ module Useless
2
+ module Doc
3
+ module Core
4
+
5
+ # Documentation for an HTTP body, belonging either to the request or the
6
+ # response.
7
+ #
8
+ # @!attribute [r] content_type
9
+ # @return [String] the MIME type of the body.
10
+ #
11
+ # @!attribute [r] attributes
12
+ # @return [Array<Body::Attribute>] documentation for each of the body
13
+ # attributes.
14
+ #
15
+ class Body
16
+
17
+ attr_reader :content_type, :attributes
18
+
19
+ # @param [Hash] attrs corresponds to the class's instance attributes.
20
+ #
21
+ def initialize(attrs)
22
+ @content_type = attrs[:content_type]
23
+ @attributes = attrs[:attributes]
24
+ end
25
+
26
+ # Documentation for an attribute on an HTTP body.
27
+ #
28
+ # @!attribute [r] key
29
+ # @return [String] the key of this attribute in the body.
30
+ #
31
+ # @!attribute [r] value_type
32
+ # @return [String] one of "string", "number", "object",
33
+ # "array", or "boolean". "string" is the default value.
34
+ #
35
+ # @!attribute [r] required
36
+ # @return [Boolean] whether or not the attribute is required. If it
37
+ # is required, and the attribute is omitted, the response should have
38
+ # a 4xx code. +true+ is the default value.
39
+ #
40
+ # @!attribute [r] description
41
+ # @return [String] a description of the attribute.
42
+ #
43
+ class Attribute
44
+
45
+ attr_reader :key, :type, :required, :default, :description
46
+
47
+ # @param [Hash] attrs corresponds to the class's instance attributes.
48
+ #
49
+ def initialize(attrs)
50
+ @key = attrs[:key]
51
+ @type = attrs[:type] || 'string'
52
+ @required = attrs.key?(:required) ? attrs[:required] : true
53
+ @default = attrs[:default]
54
+ @description = attrs[:description]
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,26 @@
1
+ module Useless
2
+ module Doc
3
+ module Core
4
+
5
+ # Documentation for an HTTP header, belonging either to the request or the
6
+ # response.
7
+ #
8
+ # @!attribute [r] key
9
+ # @return [String] the key of the header.
10
+ #
11
+ # @!attribute [r] description
12
+ # @return [String] a description of the header.
13
+ #
14
+ class Header
15
+ attr_accessor :key, :description
16
+
17
+ # @param [Hash] attrs corresponds to the class's instance attributes.
18
+ #
19
+ def initialize(attrs = {})
20
+ @key = attrs[:key]
21
+ @description = attrs[:description]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,106 @@
1
+ module Useless
2
+ module Doc
3
+ module Core
4
+
5
+ # Documentation for an HTTP request.
6
+ #
7
+ # @!attribute [r] method
8
+ # @return [String] the request's HTTP method.
9
+ # @see Useless::Doc::Core::Request::Method
10
+ #
11
+ # @!attribute [r] description
12
+ # @return [String] a description of the request.
13
+ #
14
+ # @!attribute [r] authentication_required
15
+ # @return [Boolean] whether or not the user needs to authenticate in
16
+ # order to perform this request.
17
+ #
18
+ # @!attribute [r] parameters
19
+ # @return [Array<Request::Parameter>] possible parameters for the
20
+ # request.
21
+ # @see Useless::Doc::Core::Request::Parameter
22
+ #
23
+ # @!attribute [r] headers
24
+ # @return [Array<Header>] possible headers for the request.
25
+ # @see Useless::Doc::Core::Heaader
26
+ #
27
+ # @!attribute [r] body
28
+ # @return [Body] the body of the request.
29
+ # @see Useless::Doc::Core::Body
30
+ #
31
+ # @!attribute [r] responses
32
+ # @return [Array<Response>] possible responses to the request.
33
+ # @see Useless::Doc::Core::Response
34
+ #
35
+ class Request
36
+
37
+ module Method
38
+ GET = 'GET'
39
+ HEAD = 'HEAD'
40
+ POST = 'POST'
41
+ PUT = 'PUT'
42
+ PATCH = 'PATCH'
43
+ DELETE = 'DELETE'
44
+ TRACE = 'TRACE'
45
+ CONNECT = 'CONNECT'
46
+ end
47
+
48
+ attr_accessor :method, :description, :authentication_required,
49
+ :parameters, :headers, :body, :responses
50
+
51
+ # @param [Hash] attrs corresponds to the class's instance attributes.
52
+ #
53
+ def initialize(attrs = {})
54
+ @method = attrs[:method]
55
+ @description = attrs[:description]
56
+ @authentication_required = attrs[:authentication_required]
57
+ @parameters = attrs[:parameters]
58
+ @headers = attrs[:headers]
59
+ @body = attrs[:body]
60
+ @responses = attrs[:responses]
61
+ end
62
+
63
+ # Documentation for a request parameter for an API action.
64
+ #
65
+ # @!attribute [r] type
66
+ # @return [String] either "path" if it's part of the URL path, or
67
+ # "query" if it's part of the query string.
68
+ #
69
+ # @!attribute [r] key
70
+ # @return [String] the key of the parameter.
71
+ #
72
+ # @!attribute [r] required
73
+ # @return [Boolean] whether or not the parameter is required. If it is
74
+ # required, and the attribute is omitted, the response should have a
75
+ # 4xx code.
76
+ #
77
+ # @!attribute [r] default
78
+ # @return [String, Numeric] the value used if the parameter is omitted
79
+ # and is not required.
80
+ #
81
+ # @!attribute [r] description
82
+ # @return [String] a description of the parameter.
83
+ #
84
+ class Parameter
85
+
86
+ module Type
87
+ PATH = 'path'
88
+ QUERY = 'query'
89
+ end
90
+
91
+ attr_reader :type, :key, :required, :default, :description
92
+
93
+ # @param [Hash] attrs corresponds to the class's instance attributes.
94
+ #
95
+ def initialize(attrs = {})
96
+ @type = attrs[:type]
97
+ @key = attrs[:key]
98
+ @required = attrs[:required]
99
+ @default = attrs[:default]
100
+ @description = attrs[:description]
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,32 @@
1
+ module Useless
2
+ module Doc
3
+ module Core
4
+
5
+ # Documentation for an API resource.
6
+ #
7
+ # @!attribute [r] path
8
+ # @return [String] the path segment of the resource URL.
9
+ #
10
+ # @!attribute [r] description
11
+ # @return [String] a description of the resource.
12
+ #
13
+ # @!attribute [r] requests
14
+ # @return [Array<Request>] requests that could possibly be made
15
+ # against this resource.
16
+ # @see Useless::Doc::Core::Request
17
+ #
18
+ class Resource
19
+
20
+ attr_reader :path, :description, :requests
21
+
22
+ # @param [Hash] attrs corresponds to the class's instance attributes.
23
+ #
24
+ def initialize(attrs = {})
25
+ @path = attrs[:path]
26
+ @description = attrs[:description]
27
+ @requests = attrs[:requests]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,8 +1,8 @@
1
1
  module Useless
2
2
  module Doc
3
- class Response
3
+ module Core
4
4
 
5
- # Documentation for a response status for an API action.
5
+ # Documentation for an HTTP response.
6
6
  #
7
7
  # @!attribute [r] code
8
8
  # @return [Integer] the HTTP status code of the response.
@@ -11,15 +11,23 @@ module Useless
11
11
  # @return [String] a description of the rationale for
12
12
  # the response.
13
13
  #
14
- class Status
15
-
16
- attr_reader :code, :description
14
+ # @!attribute [r] headers
15
+ # @return [Array<Header>] the significant headers of the response.
16
+ # @see Useless::Doc::Core::Header
17
+ #
18
+ # @!attribute [r] body
19
+ # @return [Body] the body of the response.
20
+ #
21
+ class Response
22
+ attr_accessor :code, :description, :status, :headers, :body
17
23
 
18
24
  # @param [Hash] attrs corresponds to the class's instance attributes.
19
25
  #
20
26
  def initialize(attrs = {})
21
27
  @code = attrs[:code]
22
28
  @description = attrs[:description]
29
+ @headers = attrs[:headers]
30
+ @body = attrs[:body]
23
31
  end
24
32
  end
25
33
  end
@@ -1,11 +1,8 @@
1
- require 'useless/doc/action'
2
- require 'useless/doc/body'
3
- require 'useless/doc/header'
4
- require 'useless/doc/request'
5
- require 'useless/doc/request/parameter'
6
- require 'useless/doc/resource'
7
- require 'useless/doc/response'
8
- require 'useless/doc/response/status'
1
+ require 'useless/doc/core/body'
2
+ require 'useless/doc/core/header'
3
+ require 'useless/doc/core/request'
4
+ require 'useless/doc/core/resource'
5
+ require 'useless/doc/core/response'
9
6
 
10
7
  module Useless
11
8
  module Doc
@@ -19,15 +16,10 @@ module Useless
19
16
  #
20
17
  # get 'Returns a full listing of the resources.' do
21
18
  # authentication_required false
19
+ # parameter 'page', 'The page of resources to be returned.'
20
+ # header 'X-Twiddle', 'The twiddle threshold.'
22
21
  #
23
- # request do
24
- # parameter 'page', 'The page of resources to be returned.'
25
- # header 'X-Twiddle', 'The twiddle threshold.'
26
- # end
27
- #
28
- # response do
29
- # status 200, 'The resources were returned successfully.'
30
- #
22
+ # response 200, 'The resources were returned successfully.' do
31
23
  # header 'X-Twonk', 'The twonk coefficient.'
32
24
  #
33
25
  # body do
@@ -44,7 +36,7 @@ module Useless
44
36
  module ClassMethods
45
37
  def build(attributes = {}, &block)
46
38
  resource = new(attributes)
47
- resource.instance_eval(&block)
39
+ resource.instance_eval(&block) if block_given?
48
40
  resource.generate
49
41
  end
50
42
  end
@@ -59,7 +51,7 @@ module Useless
59
51
 
60
52
  def generate
61
53
  name = self.class.name.split('::').last
62
- klass = eval("Doc::#{name}")
54
+ klass = eval("Doc::Core::#{name}")
63
55
  klass.new(@attributes)
64
56
  end
65
57
 
@@ -72,7 +64,7 @@ module Useless
72
64
  include DSL::Member
73
65
 
74
66
  def default_attributes
75
- { actions: [] }
67
+ { requests: [] }
76
68
  end
77
69
 
78
70
  def path(path)
@@ -84,48 +76,52 @@ module Useless
84
76
  end
85
77
 
86
78
  def get(description = nil, &block)
87
- method(Doc::Action::Method::GET, description, &block)
79
+ method(Doc::Core::Request::Method::GET, description, &block)
88
80
  end
89
81
 
90
82
  def head(description = nil, &block)
91
- method(Doc::Action::Method::HEAD, description, &block)
83
+ method(Doc::Core::Request::Method::HEAD, description, &block)
92
84
  end
93
85
 
94
86
  def post(description = nil, &block)
95
- method(Doc::Action::Method::POST, description, &block)
87
+ method(Doc::Core::Request::Method::POST, description, &block)
96
88
  end
97
89
 
98
90
  def put(description = nil, &block)
99
- method(Doc::Action::Method::PUT, description, &block)
91
+ method(Doc::Core::Request::Method::PUT, description, &block)
100
92
  end
101
93
 
102
94
  def patch(description = nil, &block)
103
- method(Doc::Action::Method::PATCH, description, &block)
95
+ method(Doc::Core::Request::Method::PATCH, description, &block)
104
96
  end
105
97
 
106
98
  def delete(description = nil, &block)
107
- method(Doc::Action::Method::DELETE, description, &block)
99
+ method(Doc::Core::Request::Method::DELETE, description, &block)
108
100
  end
109
101
 
110
102
  def trace(description = nil, &block)
111
- method(Doc::Action::Method::TRACE, description, &block)
103
+ method(Doc::Core::Request::Method::TRACE, description, &block)
112
104
  end
113
105
 
114
106
  def connect(description = nil, &block)
115
- method(Doc::Action::Method::CONNECT, description, &block)
107
+ method(Doc::Core::Request::Method::CONNECT, description, &block)
116
108
  end
117
109
 
118
110
  private
119
111
 
120
112
  def method(type, description, &block)
121
113
  attributes = { method: type, description: description }
122
- @attributes[:actions] << Action.build(attributes, &block)
114
+ @attributes[:requests] << Request.build(attributes, &block)
123
115
  end
124
116
  end
125
117
 
126
- class Action
118
+ class Request
127
119
  include DSL::Member
128
120
 
121
+ def default_attributes
122
+ { parameters: [], headers: [], responses: [] }
123
+ end
124
+
129
125
  def description(description)
130
126
  @attributes[:description] = description
131
127
  end
@@ -134,51 +130,43 @@ module Useless
134
130
  @attributes[:authentication_required] = value.nil? ? true : value
135
131
  end
136
132
 
137
- def request(&block)
138
- @attributes[:request] = Request.build({}, &block)
139
- end
140
-
141
- def response(&block)
142
- @attributes[:response] = Response.build({}, &block)
143
- end
144
- end
145
-
146
- class Request
147
- include DSL::Member
148
-
149
- def default_attributes
150
- { parameters: [], headers: [] }
151
- end
152
-
153
133
  def parameter(key, description, attributes = {})
154
- parameter = Doc::Request::Parameter.new attributes.merge(key: key, description: description)
134
+ parameter = Doc::Core::Request::Parameter.new attributes.merge(key: key, description: description)
155
135
  @attributes[:parameters] << parameter
156
136
  end
157
137
 
158
138
  def header(key, description)
159
- header = Doc::Header.new key: key, description: description
139
+ header = Doc::Core::Header.new key: key, description: description
160
140
  @attributes[:headers] << header
161
141
  end
162
142
 
163
143
  def body(&block)
164
144
  @attributes[:body] = Body.build({}, &block)
165
145
  end
146
+
147
+ def response(code, description, &block)
148
+ response = Response.build({ code: code, description: description }, &block)
149
+ @attributes[:responses] << response
150
+ end
166
151
  end
167
152
 
168
153
  class Response
169
154
  include DSL::Member
170
155
 
171
156
  def default_attributes
172
- { statuses: [], headers: [] }
157
+ { headers: [] }
158
+ end
159
+
160
+ def code(code)
161
+ @attributes[:code] = code
173
162
  end
174
163
 
175
- def status(code, description)
176
- status = Doc::Response::Status.new code: code, description: description
177
- @attributes[:statuses] << status
164
+ def description(description)
165
+ @attributes[:description] = description
178
166
  end
179
167
 
180
168
  def header(key, description)
181
- header = Doc::Header.new key: key, description: description
169
+ header = Doc::Core::Header.new key: key, description: description
182
170
  @attributes[:headers] << header
183
171
  end
184
172
 
@@ -199,7 +187,7 @@ module Useless
199
187
  end
200
188
 
201
189
  def attribute(key, description, attributes = {})
202
- attribute = Doc::Body::Attribute.new attributes.merge(key: key, description: description)
190
+ attribute = Doc::Core::Body::Attribute.new attributes.merge(key: key, description: description)
203
191
  @attributes[:attributes] << attribute
204
192
  end
205
193
  end
@@ -1,5 +1,4 @@
1
1
  require 'uri'
2
- require 'typhoeus'
3
2
  require 'rack/request'
4
3
 
5
4
  module Useless
@@ -39,7 +38,7 @@ module Useless
39
38
 
40
39
  request = ::Rack::Request.new(env)
41
40
 
42
- if valid_subdomain?(request.url)
41
+ if true or valid_subdomain?(request.url)
43
42
  url = Proxy.transform_url(request.url)
44
43
 
45
44
  if json = env['useless.doc.retriever'].retrieve(url)
@@ -1,3 +1,5 @@
1
+ require 'typhoeus'
2
+
1
3
  module Useless
2
4
  module Doc
3
5
  module Rack
@@ -29,19 +29,7 @@ module Useless
29
29
  hash_to_json \
30
30
  'path' => resource.path,
31
31
  'description' => resource.description,
32
- 'actions' => resource.actions.map { |action| action(action) }
33
- end
34
- end
35
-
36
- # @api private
37
- def self.action(action)
38
- if action
39
- hash_to_json \
40
- 'description' => action.description,
41
- 'method' => action.method,
42
- 'authentication_required' => action.authentication_required,
43
- 'request' => request(action.request),
44
- 'response' => response(action.response)
32
+ 'requests' => resource.requests.map { |request| request(request) }
45
33
  end
46
34
  end
47
35
 
@@ -49,9 +37,13 @@ module Useless
49
37
  def self.request(request)
50
38
  if request
51
39
  hash_to_json \
40
+ 'method' => request.method,
41
+ 'description' => request.description,
42
+ 'authentication_required' => request.authentication_required,
52
43
  'parameters' => request.parameters.map { |parameter| request_parameter(parameter) },
53
44
  'headers' => request.headers.map { |header| header(header) },
54
- 'body' => body(request.body)
45
+ 'body' => body(request.body),
46
+ 'responses' => request.responses.map { |response| response(response) }
55
47
  end
56
48
  end
57
49
 
@@ -59,7 +51,8 @@ module Useless
59
51
  def self.response(response)
60
52
  if response
61
53
  hash_to_json \
62
- 'statuses' => response.statuses.map { |status| response_status(status) },
54
+ 'code' => response.code,
55
+ 'description' => response.description,
63
56
  'headers' => response.headers.map { |header| header(header) },
64
57
  'body' => body(response.body)
65
58
  end
@@ -1,13 +1,10 @@
1
1
  require 'oj'
2
2
 
3
- require 'useless/doc/action'
4
- require 'useless/doc/body'
5
- require 'useless/doc/header'
6
- require 'useless/doc/request'
7
- require 'useless/doc/request/parameter'
8
- require 'useless/doc/resource'
9
- require 'useless/doc/response'
10
- require 'useless/doc/response/status'
3
+ require 'useless/doc/core/body'
4
+ require 'useless/doc/core/header'
5
+ require 'useless/doc/core/request'
6
+ require 'useless/doc/core/resource'
7
+ require 'useless/doc/core/response'
11
8
 
12
9
  module Useless
13
10
  module Doc
@@ -37,34 +34,14 @@ module Useless
37
34
  def self.resource(json)
38
35
  hash = json_to_hash json
39
36
 
40
- actions = (hash['actions'] || []).map do |json|
41
- action(json)
37
+ requests = (hash['requests'] || []).map do |json|
38
+ request json
42
39
  end
43
40
 
44
- Useless::Doc::Resource.new \
41
+ Useless::Doc::Core::Resource.new \
45
42
  path: hash['path'],
46
43
  description: hash['description'],
47
- actions: actions
48
- end
49
-
50
- # @api private
51
- def self.action(json)
52
- hash = json_to_hash json
53
-
54
- if hash['request']
55
- request = request hash['request']
56
- end
57
-
58
- if hash['response']
59
- response = response hash['response']
60
- end
61
-
62
- Useless::Doc::Action.new \
63
- description: hash['description'],
64
- method: hash['method'],
65
- authentication_required: hash['authentication_required'],
66
- request: request,
67
- response: response
44
+ requests: requests
68
45
  end
69
46
 
70
47
  # @api private
@@ -83,20 +60,24 @@ module Useless
83
60
  body = body hash['body']
84
61
  end
85
62
 
86
- Useless::Doc::Request.new \
87
- parameters: parameters,
88
- headers: headers,
89
- body: body
63
+ responses = (hash['responses'] || []).map do |json|
64
+ response json
65
+ end
66
+
67
+ Useless::Doc::Core::Request.new \
68
+ method: hash['method'],
69
+ description: hash['description'],
70
+ authentication_required: hash['authentication_required'],
71
+ parameters: parameters,
72
+ headers: headers,
73
+ body: body,
74
+ responses: responses
90
75
  end
91
76
 
92
77
  # @api private
93
78
  def self.response(json)
94
79
  hash = json_to_hash json
95
80
 
96
- statuses = (hash['statuses'] || []).map do |json|
97
- response_statuses json
98
- end
99
-
100
81
  headers = (hash['headers'] || []).map do |json|
101
82
  header json
102
83
  end
@@ -105,17 +86,18 @@ module Useless
105
86
  body = body hash['body']
106
87
  end
107
88
 
108
- Useless::Doc::Response.new \
109
- statuses: statuses,
110
- headers: headers,
111
- body: body
89
+ Useless::Doc::Core::Response.new \
90
+ code: hash['code'],
91
+ description: hash['description'],
92
+ headers: headers,
93
+ body: body
112
94
  end
113
95
 
114
96
  # @api private
115
97
  def self.request_parameter(json)
116
98
  hash = json_to_hash json
117
99
 
118
- Useless::Doc::Request::Parameter.new \
100
+ Useless::Doc::Core::Request::Parameter.new \
119
101
  type: hash['type'],
120
102
  key: hash['key'],
121
103
  required: hash['required'],
@@ -127,7 +109,7 @@ module Useless
127
109
  def self.header(json)
128
110
  hash = json_to_hash json
129
111
 
130
- Useless::Doc::Header.new \
112
+ Useless::Doc::Core::Header.new \
131
113
  key: hash['key'],
132
114
  description: hash['description']
133
115
  end
@@ -140,7 +122,7 @@ module Useless
140
122
  body_attribute json
141
123
  end
142
124
 
143
- Useless::Doc::Body.new \
125
+ Useless::Doc::Core::Body.new \
144
126
  content_type: hash['content_type'],
145
127
  attributes: attributes
146
128
  end
@@ -149,22 +131,13 @@ module Useless
149
131
  def self.body_attribute(json)
150
132
  hash = json_to_hash json
151
133
 
152
- Useless::Doc::Body::Attribute.new \
134
+ Useless::Doc::Core::Body::Attribute.new \
153
135
  key: hash['key'],
154
136
  type: hash['type'],
155
137
  required: hash['required'],
156
138
  default: hash['default'],
157
139
  description: hash['description']
158
140
  end
159
-
160
- # @api private
161
- def self.response_statuses(json)
162
- hash = json_to_hash json
163
-
164
- Useless::Doc::Response::Status.new \
165
- code: hash['code'],
166
- description: hash['description']
167
- end
168
141
  end
169
142
  end
170
143
  end