interpol 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +0 -2
- data/lib/interpol/configuration.rb +28 -24
- data/lib/interpol/endpoint.rb +35 -7
- data/lib/interpol/version.rb +1 -1
- metadata +20 -5
- data/lib/interpol/configuration_ruby_18_extensions.rb +0 -27
data/Gemfile
CHANGED
@@ -13,8 +13,6 @@ gem 'compass_twitter_bootstrap', :git => 'git://github.com/vwall/compass-twitter
|
|
13
13
|
|
14
14
|
gem 'json', :platform => 'ruby_18'
|
15
15
|
|
16
|
-
gem 'sinatra', '>= 1.3.2', '< 2.0.0'
|
17
|
-
|
18
16
|
gem 'cane', '~> 2.0', :platform => 'ruby_19'
|
19
17
|
|
20
18
|
gem 'rspec-fire', :git => 'git://github.com/xaviershay/rspec-fire.git'
|
@@ -1,7 +1,7 @@
|
|
1
|
+
require 'interpol'
|
1
2
|
require 'interpol/endpoint'
|
2
3
|
require 'interpol/errors'
|
3
4
|
require 'yaml'
|
4
|
-
require 'interpol/configuration_ruby_18_extensions' if RUBY_VERSION.to_f < 1.9
|
5
5
|
require 'uri'
|
6
6
|
|
7
7
|
module Interpol
|
@@ -33,8 +33,9 @@ module Interpol
|
|
33
33
|
|
34
34
|
# Public: Defines interpol configuration.
|
35
35
|
class Configuration
|
36
|
-
attr_reader :endpoint_definition_files, :endpoints, :filter_example_data_blocks
|
37
|
-
|
36
|
+
attr_reader :endpoint_definition_files, :endpoints, :filter_example_data_blocks,
|
37
|
+
:endpoint_definition_merge_key_files
|
38
|
+
attr_accessor :validation_mode, :documentation_title
|
38
39
|
|
39
40
|
def initialize
|
40
41
|
self.endpoint_definition_files = []
|
@@ -48,16 +49,25 @@ module Interpol
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def endpoint_definition_files=(files)
|
51
|
-
|
52
|
-
Endpoint.new(deserialized_hash_from file)
|
53
|
-
end
|
52
|
+
@endpoints = nil
|
54
53
|
@endpoint_definition_files = files
|
55
54
|
end
|
56
55
|
|
56
|
+
def endpoint_definition_merge_key_files=(files)
|
57
|
+
@endpoints = nil
|
58
|
+
@endpoint_definition_merge_key_files = files
|
59
|
+
end
|
60
|
+
|
57
61
|
def endpoints=(endpoints)
|
58
62
|
@endpoints = endpoints.extend(DefinitionFinder)
|
59
63
|
end
|
60
64
|
|
65
|
+
def endpoints
|
66
|
+
@endpoints ||= @endpoint_definition_files.map do |file|
|
67
|
+
Endpoint.new(deserialized_hash_from(file), self)
|
68
|
+
end.extend(DefinitionFinder)
|
69
|
+
end
|
70
|
+
|
61
71
|
[:request, :response].each do |type|
|
62
72
|
class_eval <<-EOEVAL, __FILE__, __LINE__ + 1
|
63
73
|
def #{type}_version(version = nil, &block)
|
@@ -156,6 +166,15 @@ module Interpol
|
|
156
166
|
selector.call(endpoint_def, env)
|
157
167
|
end
|
158
168
|
|
169
|
+
def scalars_nullable_by_default=(value)
|
170
|
+
@endpoints = nil
|
171
|
+
@scalars_nullable_by_default = value
|
172
|
+
end
|
173
|
+
|
174
|
+
def scalars_nullable_by_default?
|
175
|
+
@scalars_nullable_by_default
|
176
|
+
end
|
177
|
+
|
159
178
|
def self.default
|
160
179
|
@default ||= Configuration.new
|
161
180
|
end
|
@@ -183,24 +202,9 @@ module Interpol
|
|
183
202
|
end
|
184
203
|
|
185
204
|
private
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
BAD_ALIAS_ERROR = defined?(::Psych::BadAlias) ?
|
190
|
-
::Psych::BadAlias : TypeError
|
191
|
-
def deserialized_hash_from(file)
|
192
|
-
YAML.load(yaml_content_for file)
|
193
|
-
rescue BAD_ALIAS_ERROR => e
|
194
|
-
raise ConfigurationError.new \
|
195
|
-
"Received an error while loading YAML from #{file}: \"" +
|
196
|
-
"#{e.class}: #{e.message}\" If you are using YAML merge keys " +
|
197
|
-
"to declare shared types, you must configure endpoint_definition_merge_key_files " +
|
198
|
-
"before endpoint_definition_files.", e
|
199
|
-
end
|
200
|
-
}
|
201
|
-
|
202
|
-
# Needed to override deserialized_hash_from for Ruby 1.8
|
203
|
-
include Interpol::ConfigurationRuby18Extensions if RUBY_VERSION.to_f < 1.9
|
205
|
+
def deserialized_hash_from(file)
|
206
|
+
YAML.load(yaml_content_for file)
|
207
|
+
end
|
204
208
|
|
205
209
|
def yaml_content_for(file)
|
206
210
|
File.read(file).gsub(/\A---\n/, "---\n" + endpoint_merge_keys + "\n\n")
|
data/lib/interpol/endpoint.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'json-schema'
|
2
2
|
require 'interpol/errors'
|
3
3
|
require 'forwardable'
|
4
|
+
require 'set'
|
4
5
|
|
5
6
|
module JSON
|
6
7
|
# The JSON-schema namespace
|
@@ -65,13 +66,14 @@ module Interpol
|
|
65
66
|
# based on the endpoint definitions in the YAML files.
|
66
67
|
class Endpoint
|
67
68
|
include HashFetcher
|
68
|
-
attr_reader :name, :route, :method, :custom_metadata
|
69
|
+
attr_reader :name, :route, :method, :custom_metadata, :configuration
|
69
70
|
|
70
|
-
def initialize(endpoint_hash)
|
71
|
+
def initialize(endpoint_hash, configuration = Interpol.default_configuration)
|
71
72
|
@name = fetch_from(endpoint_hash, 'name')
|
72
73
|
@route = fetch_from(endpoint_hash, 'route')
|
73
74
|
@method = fetch_from(endpoint_hash, 'method').downcase.to_sym
|
74
75
|
|
76
|
+
@configuration = configuration
|
75
77
|
@custom_metadata = endpoint_hash.fetch('meta') { {} }
|
76
78
|
|
77
79
|
@definitions_hash, @all_definitions = extract_definitions_from(endpoint_hash)
|
@@ -181,7 +183,7 @@ module Interpol
|
|
181
183
|
attr_reader :endpoint, :message_type, :version, :schema,
|
182
184
|
:path_params, :query_params, :examples, :custom_metadata
|
183
185
|
extend Forwardable
|
184
|
-
def_delegators :endpoint, :route
|
186
|
+
def_delegators :endpoint, :route, :configuration
|
185
187
|
|
186
188
|
DEFAULT_PARAM_HASH = { 'type' => 'object', 'properties' => {} }
|
187
189
|
|
@@ -244,12 +246,14 @@ module Interpol
|
|
244
246
|
end
|
245
247
|
end
|
246
248
|
|
247
|
-
def make_schema_hash_strict!(raw_schema,
|
249
|
+
def make_schema_hash_strict!(raw_schema, make_this_schema_strict=true)
|
250
|
+
conditionally_make_nullable(raw_schema) if make_this_schema_strict
|
251
|
+
|
248
252
|
raw_schema.each do |key, value|
|
249
253
|
make_schema_strict!(value, key != 'properties')
|
250
254
|
end
|
251
255
|
|
252
|
-
return unless
|
256
|
+
return unless make_this_schema_strict
|
253
257
|
|
254
258
|
if raw_schema.has_key?('properties')
|
255
259
|
raw_schema['additionalProperties'] ||= false
|
@@ -258,9 +262,33 @@ module Interpol
|
|
258
262
|
raw_schema['required'] = !raw_schema.delete('optional')
|
259
263
|
end
|
260
264
|
|
261
|
-
def make_schema_array_strict!(raw_schema,
|
265
|
+
def make_schema_array_strict!(raw_schema, make_nested_schemas_strict=true)
|
262
266
|
raw_schema.each do |entry|
|
263
|
-
make_schema_strict!(entry,
|
267
|
+
make_schema_strict!(entry, make_nested_schemas_strict)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def conditionally_make_nullable(raw_schema)
|
272
|
+
return unless should_be_nullable?(raw_schema)
|
273
|
+
|
274
|
+
types = Array(raw_schema['type'])
|
275
|
+
return if types.none? || types.include?('null')
|
276
|
+
|
277
|
+
raw_schema['type'] = (types << "null")
|
278
|
+
end
|
279
|
+
|
280
|
+
def should_be_nullable?(raw_schema)
|
281
|
+
raw_schema.fetch('nullable') do
|
282
|
+
configuration.scalars_nullable_by_default? && scalar?(raw_schema)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
NON_SCALAR_TYPES = %w[ object array ]
|
287
|
+
def scalar?(raw_schema)
|
288
|
+
types = Array(raw_schema['type']).to_set
|
289
|
+
|
290
|
+
NON_SCALAR_TYPES.none? do |non_scalar|
|
291
|
+
types.include?(non_scalar)
|
264
292
|
end
|
265
293
|
end
|
266
294
|
|
data/lib/interpol/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interpol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -66,14 +66,14 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '2.
|
69
|
+
version: '2.13'
|
70
70
|
none: false
|
71
71
|
type: :development
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '2.
|
76
|
+
version: '2.13'
|
77
77
|
none: false
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: rspec-fire
|
@@ -171,6 +171,22 @@ dependencies:
|
|
171
171
|
- !ruby/object:Gem::Version
|
172
172
|
version: '1.2'
|
173
173
|
none: false
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: sinatra
|
176
|
+
prerelease: false
|
177
|
+
requirement: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ~>
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '1.4'
|
182
|
+
none: false
|
183
|
+
type: :development
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - ~>
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: '1.4'
|
189
|
+
none: false
|
174
190
|
description: Interpol is a toolkit for working with API endpoint definition files,
|
175
191
|
giving you a stub app, a schema validation middleware, and browsable documentation.
|
176
192
|
email:
|
@@ -186,7 +202,6 @@ files:
|
|
186
202
|
- lib/interpol/configuration/built_in_param_parsers.rb
|
187
203
|
- lib/interpol/configuration/default_callbacks.rb
|
188
204
|
- lib/interpol/configuration.rb
|
189
|
-
- lib/interpol/configuration_ruby_18_extensions.rb
|
190
205
|
- lib/interpol/documentation.rb
|
191
206
|
- lib/interpol/documentation_app/config.rb
|
192
207
|
- lib/interpol/documentation_app.rb
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Interpol
|
2
|
-
module ConfigurationRuby18Extensions
|
3
|
-
def deserialized_hash_from(file)
|
4
|
-
YAML.load(yaml_content_for file).tap do |yaml|
|
5
|
-
if bad_class = bad_deserialized_yaml(yaml)
|
6
|
-
raise ConfigurationError.new \
|
7
|
-
"Received an error while loading YAML from #{file}: \"" +
|
8
|
-
"Got object of type: #{bad_class}\"\n If you are using YAML merge keys " +
|
9
|
-
"to declare shared types, you must configure endpoint_definition_merge_key_files " +
|
10
|
-
"before endpoint_definition_files."
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# returns nil if the YAML has been only partially deserialized by Syck
|
16
|
-
# and there are YAML::Syck objects.
|
17
|
-
def bad_deserialized_yaml(yaml)
|
18
|
-
if [Hash, Array].include? yaml.class
|
19
|
-
yaml.map { |elem| bad_deserialized_yaml(elem) }.compact.first
|
20
|
-
elsif yaml.class.name =~ /YAML::Syck::/
|
21
|
-
yaml.class.name # Bad!
|
22
|
-
else
|
23
|
-
nil
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|