lurker 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -1
- data/Gemfile +1 -0
- data/features/dereferencing_through_inlining.feature +102 -0
- data/features/partials.feature +3 -1
- data/features/step_definitions/additional_cli_steps.rb +19 -0
- data/features/support/files_helper.rb +7 -0
- data/lib/lurker/endpoint.rb +85 -50
- data/lib/lurker/json/concerns/validatable.rb +47 -0
- data/lib/lurker/json/orderer.rb +19 -0
- data/lib/lurker/json/parser/expertise.rb +30 -0
- data/lib/lurker/json/parser/plain_strategy.rb +39 -0
- data/lib/lurker/json/parser/typed_strategy.rb +71 -0
- data/lib/lurker/json/parser.rb +73 -0
- data/lib/lurker/json/reader.rb +28 -0
- data/lib/lurker/json/schema/attribute.rb +115 -0
- data/lib/lurker/json/schema/extensions.rb +19 -0
- data/lib/lurker/json/schema/list.rb +51 -0
- data/lib/lurker/json/schema/object.rb +67 -0
- data/lib/lurker/json/schema/reference.rb +34 -0
- data/lib/lurker/{endpoint → json/schema}/response_codes.rb +13 -16
- data/lib/lurker/json/schema/tuple/all_of.rb +17 -0
- data/lib/lurker/json/schema/tuple/any_of.rb +17 -0
- data/lib/lurker/json/schema/tuple/one_of.rb +17 -0
- data/lib/lurker/json/schema/tuple.rb +38 -0
- data/lib/lurker/json/schema.rb +122 -0
- data/lib/lurker/json/writter.rb +58 -0
- data/lib/lurker/presenters/endpoint_presenter.rb +2 -2
- data/lib/lurker/presenters/schema_presenter.rb +4 -1
- data/lib/lurker/presenters/service_presenter.rb +8 -2
- data/lib/lurker/service.rb +4 -4
- data/lib/lurker/version.rb +1 -1
- data/lib/lurker.rb +19 -8
- data/spec/lurker/json/list_spec.rb +101 -0
- data/spec/lurker/json/schema_spec.rb +126 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/matchers/json_attribute.rb +27 -0
- data/spec/support/matchers/json_object.rb +33 -0
- data/templates/generate_stuff.rb +19 -10
- data.tar.gz.sig +2 -4
- metadata +33 -9
- metadata.gz.sig +0 -0
- data/lib/lurker/endpoint/http_parameters.rb +0 -77
- data/lib/lurker/schema.rb +0 -89
- data/lib/lurker/schema_modifier/array.rb +0 -28
- data/lib/lurker/schema_modifier/atom.rb +0 -97
- data/lib/lurker/schema_modifier/hash.rb +0 -30
- data/lib/lurker/schema_modifier.rb +0 -48
@@ -0,0 +1,28 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class Reader
|
4
|
+
attr_reader :path
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
@attempts_left = 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def read
|
12
|
+
return YAML.load_file(@path) unless @path.match(/\.erb$/)
|
13
|
+
|
14
|
+
context = Lurker::ErbSchemaContext.new
|
15
|
+
erb = ERB.new(IO.read @path).result(context.get_binding)
|
16
|
+
YAML.load(erb)
|
17
|
+
rescue Errno::ENOENT
|
18
|
+
raise if @attempts_left.zero?
|
19
|
+
|
20
|
+
@path = @path.sub(/\#\/?$/, '').sub(/\.json/, '.json.yml')
|
21
|
+
@attempts_left -= 1
|
22
|
+
|
23
|
+
retry
|
24
|
+
end
|
25
|
+
alias_method :payload, :read
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'action_dispatch'
|
2
|
+
|
3
|
+
module Lurker
|
4
|
+
module Json
|
5
|
+
class Attribute < Schema
|
6
|
+
URI = 'uri'.freeze
|
7
|
+
TYPE = 'type'.freeze
|
8
|
+
COLOR = 'color'.freeze
|
9
|
+
FORMAT = 'format'.freeze
|
10
|
+
EXAMPLE = 'example'.freeze
|
11
|
+
DATE_TIME = 'date-time'.freeze
|
12
|
+
DESCRIPTION = 'description'.freeze
|
13
|
+
|
14
|
+
TYPE_MAP = {
|
15
|
+
'Time' => 'string',
|
16
|
+
'Hash' => 'object',
|
17
|
+
'Float' => 'number',
|
18
|
+
'Fixnum' => 'integer',
|
19
|
+
'NilClass' => 'null',
|
20
|
+
'TrueClass' => 'boolean',
|
21
|
+
'FalseClass' => 'boolean',
|
22
|
+
'ActionDispatch::Http::UploadedFile' => 'string'
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
def merge!(schema)
|
26
|
+
return replace!(schema) if @schema[TYPE].blank?
|
27
|
+
|
28
|
+
schema = attributify(schema)
|
29
|
+
return if eql?(schema)
|
30
|
+
|
31
|
+
replace_options = {root_schema: root_schema, parent_schema: parent_schema,
|
32
|
+
parent_property: parent_property}
|
33
|
+
|
34
|
+
attributes_tuple = Lurker::Json::Tuple::AnyOf.new(
|
35
|
+
[to_hash, schema], replace_options)
|
36
|
+
|
37
|
+
parent_schema.replace!(parent_property, attributes_tuple)
|
38
|
+
end
|
39
|
+
|
40
|
+
def replace!(schema)
|
41
|
+
@schema.clear.merge!(attributify schema)
|
42
|
+
end
|
43
|
+
|
44
|
+
def eql?(schema)
|
45
|
+
@schema[TYPE] == attributify(schema)[TYPE]
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def parse_schema(schema)
|
51
|
+
@schema = {}
|
52
|
+
initialize_properties
|
53
|
+
|
54
|
+
if schema.is_a?(Hash)
|
55
|
+
@schema.merge!(schema)
|
56
|
+
else
|
57
|
+
@schema = attributify(schema)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def attributify(schema)
|
62
|
+
return schema if schema.is_a?(Hash) || schema.is_a?(Lurker::Json::Schema)
|
63
|
+
|
64
|
+
attribute = {
|
65
|
+
DESCRIPTION => '',
|
66
|
+
TYPE => guess_type(schema),
|
67
|
+
EXAMPLE => serialize_example(schema)
|
68
|
+
}
|
69
|
+
|
70
|
+
if format = guess_format(schema)
|
71
|
+
attribute[FORMAT] = format
|
72
|
+
end
|
73
|
+
|
74
|
+
attribute
|
75
|
+
end
|
76
|
+
|
77
|
+
def initialize_properties
|
78
|
+
@schema[DESCRIPTION] ||= ''
|
79
|
+
@schema[TYPE] ||= ''
|
80
|
+
@schema[EXAMPLE] ||= ''
|
81
|
+
end
|
82
|
+
|
83
|
+
def serialize_example(data)
|
84
|
+
if data.is_a?(ActionDispatch::Http::UploadedFile)
|
85
|
+
data.headers
|
86
|
+
else
|
87
|
+
data
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def guess_type(data)
|
92
|
+
data_type = data.class.to_s
|
93
|
+
TYPE_MAP[data_type] || data_type.downcase
|
94
|
+
end
|
95
|
+
|
96
|
+
def guess_format(data)
|
97
|
+
if data.is_a?(Time)
|
98
|
+
DATE_TIME
|
99
|
+
elsif data.is_a?(String)
|
100
|
+
if data.start_with? 'http://'
|
101
|
+
URI
|
102
|
+
elsif data.match(/\#[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?\b/)
|
103
|
+
COLOR
|
104
|
+
else
|
105
|
+
begin
|
106
|
+
DATE_TIME if Time.iso8601(data)
|
107
|
+
rescue
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class Extensions < Schema
|
4
|
+
EXTENSIONS = 'extensions'.freeze
|
5
|
+
|
6
|
+
def initialize(schema, options = {})
|
7
|
+
@parent_property = EXTENSIONS
|
8
|
+
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def merge!(schema)
|
13
|
+
return unless Lurker.upgrade?
|
14
|
+
|
15
|
+
@schema = @parser.parse_property(parent_property, schema)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class List < Schema
|
4
|
+
TYPE = 'type'.freeze
|
5
|
+
ARRAY = 'array'.freeze
|
6
|
+
ITEMS = 'items'.freeze
|
7
|
+
|
8
|
+
def merge!(schema)
|
9
|
+
if schema.is_a?(Array)
|
10
|
+
schema.each { |payload| @schema[ITEMS].merge!(payload) }
|
11
|
+
else
|
12
|
+
@schema[ITEMS].merge!(schema)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def replace!(property, schema)
|
17
|
+
if @schema[ITEMS].is_a?(Lurker::Json::Attribute)
|
18
|
+
@schema[ITEMS] = schema
|
19
|
+
else
|
20
|
+
@schema[ITEMS].replace!(property, schema)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def parse_schema(schema)
|
27
|
+
@schema = {}
|
28
|
+
initialize_properties
|
29
|
+
|
30
|
+
return if schema.empty?
|
31
|
+
|
32
|
+
schema = schema.dup
|
33
|
+
if schema.is_a?(Array)
|
34
|
+
@schema[ITEMS] = @parser.typed.parse(schema.shift)
|
35
|
+
|
36
|
+
schema.each { |payload| @schema[ITEMS].merge!(payload) }
|
37
|
+
else
|
38
|
+
@schema[ITEMS] = @parser.typed.parse(schema.delete ITEMS) if schema.key?(ITEMS)
|
39
|
+
@schema.merge!(schema)
|
40
|
+
end
|
41
|
+
|
42
|
+
@schema
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize_properties
|
46
|
+
@schema[TYPE] ||= ARRAY
|
47
|
+
@schema[ITEMS] ||= []
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class Object < Schema
|
4
|
+
TYPE = 'type'.freeze
|
5
|
+
OBJECT = 'object'.freeze
|
6
|
+
REQUIRED = 'required'.freeze
|
7
|
+
PROPERTIES = 'properties'.freeze
|
8
|
+
DESCRIPTION = 'description'.freeze
|
9
|
+
ADDITIONAL_PROPERTIES = 'additionalProperties'.freeze
|
10
|
+
|
11
|
+
def merge!(schema)
|
12
|
+
unless schema.is_a?(Hash)
|
13
|
+
return replace_with_new_type(schema) if @schema[PROPERTIES].blank?
|
14
|
+
|
15
|
+
raise TypeError, "Unable to merge #{schema.class} into JSON object"
|
16
|
+
end
|
17
|
+
|
18
|
+
schema.each do |property, property_schema|
|
19
|
+
if @schema[PROPERTIES].key?(property)
|
20
|
+
@schema[PROPERTIES][property].merge!(property_schema)
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
replace!(property, property_schema)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def replace!(property, property_schema)
|
29
|
+
@schema[PROPERTIES][property] = Lurker::Json::Parser.typed(subschema_options)
|
30
|
+
.parse_property(property, property_schema)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def parse_schema(schema)
|
36
|
+
@schema = {}
|
37
|
+
initialize_properties
|
38
|
+
|
39
|
+
schema = schema.dup
|
40
|
+
merge_required = schema.key?(PROPERTIES)
|
41
|
+
|
42
|
+
(schema.delete(PROPERTIES) || schema).each do |property, property_schema|
|
43
|
+
@schema[PROPERTIES][property] = @parser.typed.parse_property(
|
44
|
+
property, property_schema)
|
45
|
+
end
|
46
|
+
|
47
|
+
@schema.merge!(schema) if merge_required
|
48
|
+
end
|
49
|
+
|
50
|
+
def replace_with_new_type(schema)
|
51
|
+
replace_options = {root_schema: root_schema, parent_schema: parent_schema,
|
52
|
+
parent_property: parent_property}
|
53
|
+
|
54
|
+
new_schema = Lurker::Json::Parser.typed(replace_options).parse(schema)
|
55
|
+
parent_schema.replace!(parent_property, new_schema)
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize_properties
|
59
|
+
@schema[DESCRIPTION] ||= ''
|
60
|
+
@schema[TYPE] ||= OBJECT
|
61
|
+
@schema[ADDITIONAL_PROPERTIES] = !!@schema[ADDITIONAL_PROPERTIES]
|
62
|
+
@schema[REQUIRED] ||= []
|
63
|
+
@schema[PROPERTIES] ||= {}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class Reference < Schema
|
4
|
+
REF = '$ref'.freeze
|
5
|
+
|
6
|
+
attr_reader :original_uri
|
7
|
+
|
8
|
+
delegate :merge!, :replace!, :reorder!, to: :@schema
|
9
|
+
|
10
|
+
def to_original_hash(options = {})
|
11
|
+
@original_schema.to_hash
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def parse_schema(schema)
|
17
|
+
@original_schema = schema.dup
|
18
|
+
|
19
|
+
# NOTE : We decide that reference is relative, so we are using merge
|
20
|
+
# We use first read for correct relative path resolving
|
21
|
+
reader = Lurker::Json::Reader.new(@uri.merge(schema[REF]).path)
|
22
|
+
payload = reader.payload
|
23
|
+
|
24
|
+
@original_uri = parse_uri(reader.path)
|
25
|
+
@schema = @parser.plain(uri: reader.path).parse(payload)
|
26
|
+
|
27
|
+
# NOTE : The easiest way to get schema copy is to parse it again.
|
28
|
+
# It's faster and reliable
|
29
|
+
# @_schema = @parser.plain(uri: reader.path).parse(reader.payload)
|
30
|
+
# @_schema_file = URI.parse(reader.path)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,24 +1,21 @@
|
|
1
1
|
module Lurker
|
2
|
-
|
3
|
-
class ResponseCodes
|
4
|
-
RESPONSE_CODES = 'responseCodes'.freeze
|
5
|
-
DESCRIPTION = 'description'.freeze
|
6
|
-
SUCCESSFUL = 'successful'.freeze
|
2
|
+
module Json
|
3
|
+
class ResponseCodes < Schema
|
7
4
|
STATUS = 'status'.freeze
|
5
|
+
SUCCESSFUL = 'successful'.freeze
|
6
|
+
DESCRIPTION = 'description'.freeze
|
7
|
+
|
8
|
+
def initialize(schema, options = {})
|
9
|
+
@parent_property = 'responseCodes'
|
8
10
|
|
9
|
-
|
10
|
-
@schema = schema
|
11
|
-
@schema[RESPONSE_CODES] ||= []
|
11
|
+
super
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
16
|
-
STATUS => status_code,
|
17
|
-
SUCCESSFUL => successful,
|
18
|
-
DESCRIPTION => options.fetch(:description, '')
|
19
|
-
}
|
14
|
+
def merge!(status_code, successful)
|
15
|
+
return if exists?(status_code, successful)
|
20
16
|
|
21
|
-
|
17
|
+
payload = {STATUS => status_code, SUCCESSFUL => successful, DESCRIPTION => ''}
|
18
|
+
@schema << Lurker::Json::Parser.plain(root_schema: root_schema).parse(payload)
|
22
19
|
end
|
23
20
|
|
24
21
|
def validate!(status_code, successful)
|
@@ -31,7 +28,7 @@ module Lurker
|
|
31
28
|
end
|
32
29
|
|
33
30
|
def exists?(status_code, successful)
|
34
|
-
!!@schema
|
31
|
+
!!@schema.detect do |response_code|
|
35
32
|
response_code[SUCCESSFUL] == successful &&
|
36
33
|
(response_code[STATUS] == status_code || # 200
|
37
34
|
response_code[STATUS].to_i == status_code) # "200 OK"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
module Tuple
|
4
|
+
module InstanceMethods
|
5
|
+
def merge!(schema)
|
6
|
+
return if exists?(schema)
|
7
|
+
|
8
|
+
@schema[tuple_key] << @parser.typed.parse_property(
|
9
|
+
parent_property, schema)
|
10
|
+
end
|
11
|
+
|
12
|
+
def replace!(schema)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def exists?(schema)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_schema(schema)
|
23
|
+
@schema = {}
|
24
|
+
initialize_properties
|
25
|
+
|
26
|
+
schema = schema.dup
|
27
|
+
@schema[tuple_key] = (schema.delete(tuple_key) || schema).map do |payload|
|
28
|
+
@parser.typed.parse_property(parent_property, payload)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize_properties
|
33
|
+
@schema[tuple_key] ||= []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class Schema
|
4
|
+
include Lurker::Json::Concerns::Validatable
|
5
|
+
|
6
|
+
EXTENSIONS = 'extensions'.freeze
|
7
|
+
RESPONSE_CODES = 'responseCodes'.freeze
|
8
|
+
REQUEST_PARAMETERS = 'requestParameters'.freeze
|
9
|
+
RESPONSE_PARAMETERS = 'responseParameters'.freeze
|
10
|
+
|
11
|
+
attr_reader :uri, :root_schema, :parent_schema, :parent_property
|
12
|
+
|
13
|
+
def initialize(schema, options = {})
|
14
|
+
@root_schema = options[:root_schema]
|
15
|
+
@parent_schema = options[:parent_schema]
|
16
|
+
@parent_property = options[:parent_property]
|
17
|
+
@uri = parse_uri(options[:uri])
|
18
|
+
|
19
|
+
@parser = Lurker::Json::Parser.new(subschema_options)
|
20
|
+
|
21
|
+
parse_schema(schema)
|
22
|
+
end
|
23
|
+
|
24
|
+
def root?
|
25
|
+
root_schema.blank?
|
26
|
+
end
|
27
|
+
|
28
|
+
def merge!(schema)
|
29
|
+
return if schema.blank?
|
30
|
+
|
31
|
+
schema.each do |property, property_schema|
|
32
|
+
if @schema[property].is_a?(Lurker::Json::Schema)
|
33
|
+
@schema[property].merge!(property_schema)
|
34
|
+
|
35
|
+
next
|
36
|
+
end
|
37
|
+
|
38
|
+
replace!(property, property_schema)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def replace!(property, property_schema)
|
43
|
+
@schema[property] = Lurker::Json::Parser.plain(subschema_options)
|
44
|
+
.parse_property(property, property_schema)
|
45
|
+
end
|
46
|
+
|
47
|
+
def reorder!
|
48
|
+
@schema = Hash[@schema.sort]
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_hash(options = {})
|
53
|
+
hashify(@schema, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_json(options = {})
|
57
|
+
hashify(@schema, options).to_json
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_yaml(options = {})
|
61
|
+
YAML.dump(to_hash(options))
|
62
|
+
end
|
63
|
+
|
64
|
+
def method_missing(method, *args, &block)
|
65
|
+
if @schema.is_a?(Lurker::Json::Schema) || @schema.respond_to?(method)
|
66
|
+
return @schema.send(method, *args, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def hashify(object, options = {})
|
75
|
+
case object
|
76
|
+
when Lurker::Json::Reference
|
77
|
+
options[:reference] == :original ? object.to_original_hash(options)
|
78
|
+
: object.to_hash(options)
|
79
|
+
when Lurker::Json::Schema then object.to_hash(options)
|
80
|
+
when Array then object.map { |x| hashify(x, options) }
|
81
|
+
when Hash
|
82
|
+
object.each_with_object({}) do |(property, property_schema), memo|
|
83
|
+
memo[property] = hashify(property_schema, options)
|
84
|
+
end
|
85
|
+
else object
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def parse_uri(uri)
|
90
|
+
return if uri.blank?
|
91
|
+
|
92
|
+
uri = uri.respond_to?(:scheme) ? uri : URI.parse(uri)
|
93
|
+
uri.relative? ? URI.parse("file://#{uri}") : uri
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_schema(schema)
|
97
|
+
@schema = {}
|
98
|
+
|
99
|
+
unless schema.is_a?(Hash)
|
100
|
+
return @schema = @parser.plain.parse(schema)
|
101
|
+
end
|
102
|
+
|
103
|
+
schema.each do |property, property_schema|
|
104
|
+
@schema[property] = case property
|
105
|
+
when EXTENSIONS
|
106
|
+
Lurker::Json::Extensions.new(property_schema, subschema_options)
|
107
|
+
when RESPONSE_CODES
|
108
|
+
Lurker::Json::ResponseCodes.new(property_schema, subschema_options)
|
109
|
+
when REQUEST_PARAMETERS, RESPONSE_PARAMETERS
|
110
|
+
@parser.typed.parse_property(property, property_schema)
|
111
|
+
else
|
112
|
+
@parser.plain.parse_property(property, property_schema)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def subschema_options
|
118
|
+
{uri: uri, root_schema: (root? ? self : root_schema), parent_schema: self}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Lurker
|
2
|
+
module Json
|
3
|
+
class Writter
|
4
|
+
class << self
|
5
|
+
def write(schema, path)
|
6
|
+
new(path).write(schema)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(path)
|
11
|
+
@path = path
|
12
|
+
@dirname = File.dirname(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def write(schema)
|
16
|
+
write_to_file(schema)
|
17
|
+
|
18
|
+
extract_references(schema).each do |reference|
|
19
|
+
Lurker::Json::Writter.write(reference, reference.original_uri.path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# TODO : Separate schema dumping for JSON & YAML files
|
26
|
+
def write_to_file(schema)
|
27
|
+
FileUtils.mkdir_p(@dirname) unless File.directory?(@dirname)
|
28
|
+
File.open(@path, File::WRONLY | File::TRUNC | File::CREAT) do |file|
|
29
|
+
file.write(present_by_extension schema)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def extract_references(schema, memo = [])
|
34
|
+
case schema
|
35
|
+
when Array
|
36
|
+
schema.each { |payload| extract_references(payload, memo) }
|
37
|
+
when Hash, Lurker::Json::Schema
|
38
|
+
schema.each do |_, payload|
|
39
|
+
memo << payload if payload.is_a?(Lurker::Json::Reference)
|
40
|
+
extract_references(payload, memo)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
# no-op
|
44
|
+
end
|
45
|
+
|
46
|
+
memo
|
47
|
+
end
|
48
|
+
|
49
|
+
def present_by_extension(schema)
|
50
|
+
case File.extname(@path)
|
51
|
+
when '.yml' then schema.to_yaml(reference: :original)
|
52
|
+
when '.json' then JSON.pretty_generate(schema.to_hash reference: :original)
|
53
|
+
else raise TypeError, "Unknown schema file extension '#{File.extname(@path)}'"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -115,7 +115,7 @@ class Lurker::EndpointPresenter < Lurker::BasePresenter
|
|
115
115
|
# TODO: remove in favor of named_path
|
116
116
|
def path
|
117
117
|
return @path if @path
|
118
|
-
unless (@path = @endpoint.schema
|
118
|
+
unless (@path = @endpoint.schema['extensions'].try(:[], 'path_info')).present?
|
119
119
|
@path = @endpoint.path.gsub(/__/, ':')
|
120
120
|
@path = @path.gsub(/-#{@end}/) if @endpoint.schema.extensions.try(:[], 'suffix').present?
|
121
121
|
end
|
@@ -127,7 +127,7 @@ class Lurker::EndpointPresenter < Lurker::BasePresenter
|
|
127
127
|
def named_path
|
128
128
|
return @named_path if @named_path
|
129
129
|
@named_path = base_path.sub(/\/?$/, '/') + endpoint.path.gsub(/__/, ':')
|
130
|
-
if (suffix = endpoint.schema
|
130
|
+
if (suffix = endpoint.schema['extensions'].try(:[], 'suffix')).present?
|
131
131
|
@named_path = @named_path.gsub(/-#{suffix}/, '')
|
132
132
|
end
|
133
133
|
@named_path
|
@@ -48,7 +48,10 @@ class Lurker::SchemaPresenter < Lurker::BasePresenter
|
|
48
48
|
html << enum_html
|
49
49
|
|
50
50
|
(@schema.keys - FORMATTED_KEYS).each do |key|
|
51
|
-
|
51
|
+
value = @schema[key]
|
52
|
+
value = value.to_hash if value.is_a?(Lurker::Json::Schema)
|
53
|
+
|
54
|
+
html << '<li>%s: %s</li>' % [key, value]
|
52
55
|
end
|
53
56
|
|
54
57
|
html << items_html
|
@@ -22,12 +22,12 @@ class Lurker::ServicePresenter < Lurker::BasePresenter
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def domains
|
25
|
-
return
|
25
|
+
return service_domains if service_domains.present?
|
26
26
|
{ '/' => 'Local' }
|
27
27
|
end
|
28
28
|
|
29
29
|
def default_domain
|
30
|
-
return
|
30
|
+
return service_domains.to_a[0][1] if service_domains.present?
|
31
31
|
'/'
|
32
32
|
end
|
33
33
|
|
@@ -87,4 +87,10 @@ class Lurker::ServicePresenter < Lurker::BasePresenter
|
|
87
87
|
hash
|
88
88
|
end
|
89
89
|
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def service_domains
|
94
|
+
service.domains.to_hash
|
95
|
+
end
|
90
96
|
end
|