prmd 0.0.1 → 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.
- checksums.yaml +8 -8
- data/.travis.yml +2 -0
- data/Gemfile.lock +0 -2
- data/README.md +46 -26
- data/bin/prmd +16 -24
- data/docs/schemata.md +0 -2
- data/lib/prmd/commands/combine.rb +56 -2
- data/lib/prmd/commands/doc.rb +13 -9
- data/lib/prmd/commands/expand.rb +1 -6
- data/lib/prmd/commands/init.rb +47 -37
- data/lib/prmd/commands/verify.rb +24 -2
- data/lib/prmd/schema.rb +12 -53
- data/lib/prmd/version.rb +1 -1
- data/lib/prmd/views/endpoint.erb +48 -28
- data/lib/prmd.rb +1 -1
- data/prmd.gemspec +7 -8
- data/test/helpers.rb +2 -2
- data/test/schema_test.rb +26 -5
- data/test/schemas/input/meta.json +14 -0
- data/test/schemas/input/user.json +8 -11
- metadata +19 -31
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTJiYjFkZjYwZTAxYWExOTJmYzAxMWZjYmJiNmQ1YzA3ZTdiMmY0Ng==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Y2RmMDI2NTIyNzQxZTk4NjcxZmZhYzU5NTM2NDdlNmM4YWZhMTE4Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTE2N2FhODUzYjgxY2Y0YjJmOGUwYzRkYTQwYmY0Nzg2NDJhNDdjM2JhZGYy
|
10
|
+
ZjFjY2MxMGY5ZmNkYjM0OTVlMmUyNTYzMGJlYTdmYjk1MTczOTZiODI3ZjVh
|
11
|
+
MWZlYTQ2OTg2MWRlNjg3Yjc4ZmU2MThkMGVjNTc2Yjg5ZGZmMTA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjIyMmNlZmI2NGJiMjY2OGE5NWM2ZTJmMzkxMzAyM2NjNTkyOWFmMDZiMTRk
|
14
|
+
MWEwOWUwYmY0YjM3Mzk1N2FhNDE1YTdkYWJiNTY1NmUxMTE0NmQ4YjBiOTVm
|
15
|
+
Mjk5NzNmODZiNTIwNWUzY2Q3MDIxMjM0ZTRmNTEyMDFjMWU0MWY=
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,66 +1,86 @@
|
|
1
1
|
# Prmd
|
2
2
|
|
3
|
-
|
3
|
+
JSON Schema tooling: scaffold, verify, and generate documentation
|
4
|
+
against JSON Schema documents.
|
5
|
+
|
4
6
|
|
5
7
|
## Introduction
|
6
8
|
|
7
|
-
JSON-
|
9
|
+
[JSON Schema](http://json-schema.org/) provides a great way to describe
|
10
|
+
an API. prmd provides tools for bootstrapping a description like this,
|
11
|
+
verifying its completeness, and generating documentation from the
|
12
|
+
specification.
|
8
13
|
|
9
|
-
The
|
14
|
+
The JSON Schema usage conventions expected by prmd are described in
|
15
|
+
[/docs/schemata.md](/docs/schemata.md).
|
10
16
|
|
11
|
-
To learn more about
|
17
|
+
To learn more about JSON Schema in general, start with
|
18
|
+
[this excellent guide](http://spacetelescope.github.io/understanding-json-schema/)
|
19
|
+
and supplement with the [specification](http://json-schema.org/documentation.html).
|
12
20
|
|
13
21
|
## Installation
|
14
22
|
|
15
23
|
Add this line to your application's Gemfile:
|
16
24
|
|
17
|
-
|
25
|
+
```ruby
|
26
|
+
gem 'prmd'
|
27
|
+
```
|
18
28
|
|
19
29
|
And then execute:
|
20
30
|
|
21
|
-
|
31
|
+
```console
|
32
|
+
$ bundle
|
33
|
+
```
|
22
34
|
|
23
35
|
Or install it yourself as:
|
24
36
|
|
25
|
-
|
37
|
+
```console
|
38
|
+
$ gem install prmd
|
39
|
+
```
|
26
40
|
|
27
41
|
## Usage
|
28
42
|
|
29
|
-
Combine takes the path to a
|
43
|
+
Combine takes the path to a schema file or directory of schema files and
|
44
|
+
combines them on to stdout. If -m or --meta is supplied, it will override
|
45
|
+
defaults/metadata:
|
30
46
|
|
31
|
-
```
|
32
|
-
prmd combine <directory>
|
47
|
+
```console
|
48
|
+
$ prmd combine <file or directory>
|
33
49
|
```
|
34
50
|
|
35
|
-
Doc takes the path to a
|
51
|
+
Doc takes the path to a combined schema and outputs documentation to stdout.
|
52
|
+
If -m or --meta is supplied, it will override defaults/metadata:
|
36
53
|
|
37
|
-
```
|
38
|
-
prmd doc <
|
54
|
+
```console
|
55
|
+
$ prmd doc <combined schema>
|
39
56
|
```
|
40
57
|
|
41
|
-
|
58
|
+
You can also prepend files to the documention with -p or --prepend:
|
42
59
|
|
43
|
-
```
|
44
|
-
prmd doc -p header.md,overview.md <directory or schema>
|
60
|
+
```console
|
61
|
+
$ prmd doc -p header.md,overview.md <directory or schema>
|
45
62
|
```
|
46
63
|
|
47
|
-
Init optionally takes a resource as it's first argument and generates a
|
64
|
+
Init optionally takes a resource as it's first argument and generates a
|
65
|
+
new schema file to stdout (generically or using the resource name
|
66
|
+
provided). If -m or --meta is supplied, it will override
|
67
|
+
defaults/metadata:
|
48
68
|
|
49
|
-
```
|
50
|
-
prmd init
|
51
|
-
prmd init <
|
69
|
+
```console
|
70
|
+
$ prmd init
|
71
|
+
$ prmd init <resource name>
|
52
72
|
```
|
53
73
|
|
54
|
-
Verify takes a path to a
|
74
|
+
Verify takes a path to a combined schema and warns about missing attributes.
|
55
75
|
|
56
|
-
```
|
57
|
-
prmd verify <
|
76
|
+
```console
|
77
|
+
$ prmd verify <combined schema>
|
58
78
|
```
|
59
79
|
|
60
|
-
|
80
|
+
You can also chain commands as needed:
|
61
81
|
|
62
|
-
```
|
63
|
-
prmd combine <directory> | prmd verify | prmd doc > schema.md
|
82
|
+
```console
|
83
|
+
$ prmd combine <directory> | prmd verify | prmd doc > schema.md
|
64
84
|
```
|
65
85
|
|
66
86
|
## Contributing
|
data/bin/prmd
CHANGED
@@ -6,29 +6,25 @@ options = {}
|
|
6
6
|
|
7
7
|
commands = {
|
8
8
|
combine: OptionParser.new do |opts|
|
9
|
-
opts.banner = "prmd combine [options] <directory>"
|
9
|
+
opts.banner = "prmd combine [options] <file or directory>"
|
10
10
|
opts.on("-m", "--meta meta.json", "Set defaults for schemata") do |m|
|
11
11
|
options[:meta] = m
|
12
12
|
end
|
13
13
|
end,
|
14
14
|
doc: OptionParser.new do |opts|
|
15
|
-
opts.banner = "prmd doc [options] <schema>"
|
16
|
-
opts.on("-m", "--meta meta.json", "Set defaults for schemata") do |m|
|
17
|
-
options[:meta] = m
|
18
|
-
end
|
15
|
+
opts.banner = "prmd doc [options] <combined schema>"
|
19
16
|
opts.on("-p", "--prepend header,overview", Array, "Prepend files to output") do |p|
|
20
17
|
options[:prepend] = p
|
21
18
|
end
|
22
|
-
opts.banner = "prmd doc [options] <directory>"
|
23
19
|
end,
|
24
20
|
init: OptionParser.new do |opts|
|
25
|
-
opts.banner = "prmd init [options] <
|
21
|
+
opts.banner = "prmd init [options] <resource name>"
|
26
22
|
opts.on("-m", "--meta meta.json", "Set defaults for schemata") do |m|
|
27
23
|
options[:meta] = m
|
28
24
|
end
|
29
25
|
end,
|
30
26
|
verify: OptionParser.new do |opts|
|
31
|
-
opts.banner = "prmd verify [options] <
|
27
|
+
opts.banner = "prmd verify [options] <combined schema>"
|
32
28
|
end
|
33
29
|
}
|
34
30
|
|
@@ -68,37 +64,33 @@ option.order!
|
|
68
64
|
|
69
65
|
case command
|
70
66
|
when :combine
|
71
|
-
puts Prmd.combine(ARGV[0], options)
|
67
|
+
puts Prmd.combine(ARGV[0], options).to_s
|
72
68
|
when :doc
|
73
|
-
|
69
|
+
unless $stdin.tty?
|
74
70
|
data = JSON.parse($stdin.read)
|
75
|
-
schema = Prmd::Schema.new(data
|
71
|
+
schema = Prmd::Schema.new(data)
|
76
72
|
puts Prmd.doc(schema, options)
|
77
73
|
else
|
78
|
-
|
74
|
+
data = JSON.parse(File.read(ARGV[0]))
|
75
|
+
schema = Prmd::Schema.new(data)
|
79
76
|
puts Prmd.doc(schema, options)
|
80
77
|
end
|
81
78
|
when :init
|
82
79
|
puts Prmd.init(ARGV[0], options)
|
83
80
|
when :verify
|
84
|
-
errors = []
|
85
|
-
|
81
|
+
data, errors = '', []
|
82
|
+
unless $stdin.tty?
|
86
83
|
data = $stdin.read
|
87
|
-
errors
|
88
|
-
puts data
|
89
|
-
elsif File.directory?(ARGV[0])
|
90
|
-
Dir.glob(File.join(ARGV[0], '**/*.json')).each do |path|
|
91
|
-
Prmd.verify(JSON.parse(File.read(path))).each do |error|
|
92
|
-
errors << "#{path}: #{error}"
|
93
|
-
end
|
94
|
-
end
|
84
|
+
errors.concat(Prmd.verify(JSON.parse(data)))
|
95
85
|
else
|
96
|
-
|
86
|
+
data = JSON.parse(File.read(ARGV[0]))
|
87
|
+
Prmd.verify(data).each do |error|
|
97
88
|
errors << "#{ARGV[0]}: #{error}"
|
98
89
|
end
|
99
90
|
end
|
100
91
|
errors.each do |error|
|
101
|
-
$stderr.puts
|
92
|
+
$stderr.puts(error)
|
102
93
|
end
|
103
94
|
exit(1) unless errors.empty?
|
95
|
+
puts(data) unless $stdout.tty?
|
104
96
|
end
|
data/docs/schemata.md
CHANGED
@@ -42,7 +42,6 @@ Each attribute MUST include the following properties:
|
|
42
42
|
Each attribute MAY include the following properties:
|
43
43
|
|
44
44
|
* `pattern` - a regex encoded in a string that the valid values MUST match
|
45
|
-
* `readOnly` - boolean value defining if the attribute can be modified, assumes `false` if omitted
|
46
45
|
* `format` - format of the value. MUST be one of spec defined `["date-time", "email", "hostname", "ipv4", "ipv6", "uri"]` or defined by us `["uuid"]`
|
47
46
|
|
48
47
|
Examples:
|
@@ -54,7 +53,6 @@ Examples:
|
|
54
53
|
"description": "unique identifier of resource",
|
55
54
|
"example": "01234567-89ab-cdef-0123-456789abcdef",
|
56
55
|
"format": "uuid",
|
57
|
-
"readOnly": true,
|
58
56
|
"type": ["string"]
|
59
57
|
},
|
60
58
|
"url": {
|
@@ -1,5 +1,59 @@
|
|
1
1
|
module Prmd
|
2
|
-
def self.combine(
|
3
|
-
|
2
|
+
def self.combine(path, options={})
|
3
|
+
files = if File.directory?(path)
|
4
|
+
Dir.glob(File.join(path, '**', '*.json')) - [options[:meta]]
|
5
|
+
else
|
6
|
+
[path]
|
7
|
+
end
|
8
|
+
schemas = files.map { |file| JSON.parse(File.read(file)) }
|
9
|
+
|
10
|
+
data = {
|
11
|
+
'$schema' => 'http://json-schema.org/draft-04/hyper-schema',
|
12
|
+
'definitions' => {},
|
13
|
+
'properties' => {},
|
14
|
+
'type' => ['object']
|
15
|
+
}
|
16
|
+
|
17
|
+
if options[:meta] && File.exists?(options[:meta])
|
18
|
+
data.merge!(JSON.parse(File.read(options[:meta])))
|
19
|
+
end
|
20
|
+
|
21
|
+
schemas.each do |schema_data|
|
22
|
+
id = if schema_data['id']
|
23
|
+
schema_data['id'].split('/').last
|
24
|
+
end
|
25
|
+
next if id.nil? || id[0..0] == '_' # FIXME: remove this exception?
|
26
|
+
|
27
|
+
data['definitions'][id] = schema_data
|
28
|
+
reference_localizer = lambda do |datum|
|
29
|
+
case datum
|
30
|
+
when Array
|
31
|
+
datum.map {|element| reference_localizer.call(element)}
|
32
|
+
when Hash
|
33
|
+
if datum.has_key?('$ref')
|
34
|
+
if datum['$ref'].include?('/schema/')
|
35
|
+
$stderr.puts("`#{schema_data['id']}` `/schema/` prefixed refs are deprecated, use `/schemata/` prefixes")
|
36
|
+
datum['$ref'] = datum['$ref'].gsub(%r{/schema/([^#]*)#}, '#/definitions/\1')
|
37
|
+
end
|
38
|
+
datum['$ref'] = datum['$ref'].gsub(%r{/schemata/([^#]*)#}, '#/definitions/\1')
|
39
|
+
end
|
40
|
+
if datum.has_key?('href')
|
41
|
+
if datum['href'].include?('%2Fschema%2F')
|
42
|
+
$stderr.puts("`#{id}` `%2Fschema%2F` prefixed hrefs are deprecated, use `%2Fschemata%2F` prefixes")
|
43
|
+
datum['href'] = datum['href'].gsub(%r{%2Fschema%2F([^%]*)%23%2F}, '%23%2Fdefinitions%2F\1%2F')
|
44
|
+
end
|
45
|
+
datum['href'] = datum['href'].gsub(%r{%2Fschemata%2F([^%]*)%23%2F}, '%23%2Fdefinitions%2F\1%2F')
|
46
|
+
end
|
47
|
+
datum.each { |k,v| datum[k] = reference_localizer.call(v) }
|
48
|
+
else
|
49
|
+
datum
|
50
|
+
end
|
51
|
+
end
|
52
|
+
reference_localizer.call(data['definitions'][id])
|
53
|
+
|
54
|
+
data['properties'][id] = { '$ref' => "#/definitions/#{id}" }
|
55
|
+
end
|
56
|
+
|
57
|
+
Prmd::Schema.new(data)
|
4
58
|
end
|
5
59
|
end
|
data/lib/prmd/commands/doc.rb
CHANGED
@@ -2,7 +2,7 @@ def extract_attributes(schema, properties)
|
|
2
2
|
attributes = []
|
3
3
|
properties.each do |key, value|
|
4
4
|
# found a reference to another element:
|
5
|
-
value = schema.dereference(value)
|
5
|
+
_, value = schema.dereference(value)
|
6
6
|
if value.has_key?('anyOf')
|
7
7
|
descriptions = []
|
8
8
|
examples = []
|
@@ -13,7 +13,7 @@ def extract_attributes(schema, properties)
|
|
13
13
|
end
|
14
14
|
|
15
15
|
anyof.each do |ref|
|
16
|
-
nested_field = schema.dereference(ref)
|
16
|
+
_, nested_field = schema.dereference(ref)
|
17
17
|
descriptions << nested_field['description']
|
18
18
|
examples << nested_field['example']
|
19
19
|
end
|
@@ -23,7 +23,10 @@ def extract_attributes(schema, properties)
|
|
23
23
|
descriptions.first.gsub!(/ of (this )?.*/, "")
|
24
24
|
descriptions[1..-1].map { |d| d.gsub!(/unique /, "") }
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
|
+
last = descriptions.pop
|
28
|
+
description = [descriptions.join(", "), last].join(" or ")
|
29
|
+
|
27
30
|
example = doc_example(*examples)
|
28
31
|
attributes << [key, "string", description, example]
|
29
32
|
|
@@ -59,7 +62,7 @@ end
|
|
59
62
|
|
60
63
|
module Prmd
|
61
64
|
def self.doc(schema, options={})
|
62
|
-
root_url = schema['links'].find{|l| l['rel'] == '
|
65
|
+
root_url = schema['links'].find{|l| l['rel'] == 'self'}['href']
|
63
66
|
|
64
67
|
doc = (options[:prepend] || []).map do |path|
|
65
68
|
File.open(path, 'r').read + "\n"
|
@@ -73,20 +76,21 @@ module Prmd
|
|
73
76
|
identifiers = if definition['definitions']['identity'].has_key?('anyOf')
|
74
77
|
definition['definitions']['identity']['anyOf']
|
75
78
|
else
|
76
|
-
[
|
79
|
+
[definition['definitions']['identity']]
|
77
80
|
end
|
78
81
|
|
79
82
|
identifiers = identifiers.map {|ref| ref['$ref'].split('/').last }
|
80
83
|
end
|
81
84
|
if definition['properties']
|
82
85
|
definition['properties'].each do |key, value|
|
83
|
-
|
84
|
-
|
85
|
-
else
|
86
|
+
_, value = schema.dereference(value)
|
87
|
+
if value.has_key?('properties')
|
86
88
|
serialization[key] = {}
|
87
89
|
value['properties'].each do |k,v|
|
88
|
-
serialization[key][k] = schema.dereference(v)['example']
|
90
|
+
serialization[key][k] = schema.dereference(v).last['example']
|
89
91
|
end
|
92
|
+
else
|
93
|
+
serialization[key] = value['example']
|
90
94
|
end
|
91
95
|
end
|
92
96
|
else
|
data/lib/prmd/commands/expand.rb
CHANGED
@@ -39,25 +39,20 @@ if original['definitions']
|
|
39
39
|
when 'uuid'
|
40
40
|
{
|
41
41
|
'example' => '01234567-89ab-cdef-0123-456789abcdef',
|
42
|
-
'readOnly' => true,
|
43
42
|
'type' => ['string']
|
44
43
|
}
|
45
44
|
when 'email'
|
46
45
|
{
|
47
46
|
'example' => 'username@example.com',
|
48
|
-
'readOnly' => false,
|
49
47
|
'type' => ['string']
|
50
48
|
}
|
51
49
|
when 'date-time'
|
52
50
|
{
|
53
51
|
'example' => '2012-01-01T12:00:00Z',
|
54
|
-
'readOnly' => true,
|
55
52
|
'type' => ['string']
|
56
53
|
}
|
57
54
|
else
|
58
|
-
{
|
59
|
-
'readOnly' => false
|
60
|
-
}
|
55
|
+
{}
|
61
56
|
end
|
62
57
|
expanded['definitions'][key] = default.merge!(value)
|
63
58
|
end
|
data/lib/prmd/commands/init.rb
CHANGED
@@ -3,10 +3,11 @@ module Prmd
|
|
3
3
|
data = {
|
4
4
|
'$schema' => 'http://json-schema.org/draft-04/hyper-schema',
|
5
5
|
'title' => 'FIXME',
|
6
|
-
'type' => ['object'],
|
7
6
|
'definitions' => {},
|
7
|
+
'description' => 'FIXME',
|
8
8
|
'links' => [],
|
9
|
-
'properties' => {}
|
9
|
+
'properties' => {},
|
10
|
+
'type' => ['object']
|
10
11
|
}
|
11
12
|
|
12
13
|
if options[:meta] && File.exists?(options[:meta])
|
@@ -16,83 +17,92 @@ module Prmd
|
|
16
17
|
schema = Prmd::Schema.new(data)
|
17
18
|
|
18
19
|
if resource
|
19
|
-
|
20
|
+
if resource.include?('/')
|
21
|
+
parent, resource = resource.split('/')
|
22
|
+
end
|
23
|
+
schema['id'] = "schemata/#{resource}"
|
20
24
|
schema['title'] = "#{schema['title']} - #{resource[0...1].upcase}#{resource[1..-1]}"
|
21
25
|
schema['definitions'] = {
|
22
26
|
"created_at" => {
|
23
27
|
"description" => "when #{resource} was created",
|
24
28
|
"example" => "2012-01-01T12:00:00Z",
|
25
29
|
"format" => "date-time",
|
26
|
-
"readOnly" => true,
|
27
30
|
"type" => ["string"]
|
28
31
|
},
|
29
32
|
"id" => {
|
30
33
|
"description" => "unique identifier of #{resource}",
|
31
34
|
"example" => "01234567-89ab-cdef-0123-456789abcdef",
|
32
35
|
"format" => "uuid",
|
33
|
-
"readOnly" => true,
|
34
36
|
"type" => ["string"]
|
35
37
|
},
|
36
38
|
"identity" => {
|
37
|
-
"$ref" => "/
|
39
|
+
"$ref" => "/schemata/#{resource}#/definitions/id"
|
38
40
|
},
|
39
41
|
"updated_at" => {
|
40
42
|
"description" => "when #{resource} was updated",
|
41
43
|
"example" => "2012-01-01T12:00:00Z",
|
42
44
|
"format" => "date-time",
|
43
|
-
"readOnly" => true,
|
44
45
|
"type" => ["string"]
|
45
46
|
}
|
46
47
|
}
|
47
48
|
schema['links'] = [
|
48
49
|
{
|
49
|
-
"description"
|
50
|
-
"href"
|
51
|
-
"method"
|
52
|
-
"rel"
|
53
|
-
"schema"
|
50
|
+
"description" => "Create a new #{resource}.",
|
51
|
+
"href" => "/#{resource}s",
|
52
|
+
"method" => "POST",
|
53
|
+
"rel" => "create",
|
54
|
+
"schema" => {
|
54
55
|
"properties" => {},
|
55
56
|
"type" => ["object"]
|
56
57
|
},
|
57
|
-
"title"
|
58
|
+
"title" => "Create"
|
58
59
|
},
|
59
60
|
{
|
60
|
-
"description"
|
61
|
-
"href"
|
62
|
-
"method"
|
63
|
-
"rel"
|
64
|
-
"title"
|
61
|
+
"description" => "Delete an existing #{resource}.",
|
62
|
+
"href" => "/#{resource}s/{(%2Fschemata%2F#{resource}%23%2Fdefinitions%2Fidentity)}",
|
63
|
+
"method" => "DELETE",
|
64
|
+
"rel" => "destroy",
|
65
|
+
"title" => "Delete"
|
65
66
|
},
|
66
67
|
{
|
67
|
-
"description"
|
68
|
-
"href"
|
69
|
-
"method"
|
70
|
-
"rel"
|
71
|
-
"title"
|
68
|
+
"description" => "Info for existing #{resource}.",
|
69
|
+
"href" => "/#{resource}s/{(%2Fschemata%2F#{resource}%23%2Fdefinitions%2Fidentity)}",
|
70
|
+
"method" => "GET",
|
71
|
+
"rel" => "self",
|
72
|
+
"title" => "Info"
|
72
73
|
},
|
73
74
|
{
|
74
|
-
"description"
|
75
|
-
"href"
|
76
|
-
"method"
|
77
|
-
"rel"
|
78
|
-
"title"
|
75
|
+
"description" => "List existing #{resource}s.",
|
76
|
+
"href" => "/#{resource}s",
|
77
|
+
"method" => "GET",
|
78
|
+
"rel" => "instances",
|
79
|
+
"title" => "List"
|
79
80
|
},
|
80
81
|
{
|
81
|
-
"description"
|
82
|
-
"href"
|
83
|
-
"method"
|
84
|
-
"rel"
|
85
|
-
"schema"
|
82
|
+
"description" => "Update an existing #{resource}.",
|
83
|
+
"href" => "/#{resource}s/{(%2Fschemata%2F#{resource}%23%2Fdefinitions%2Fidentity)}",
|
84
|
+
"method" => "PATCH",
|
85
|
+
"rel" => "update",
|
86
|
+
"schema" => {
|
86
87
|
"properties" => {},
|
87
88
|
"type" => ["object"]
|
88
89
|
},
|
89
|
-
"title"
|
90
|
+
"title" => "Update"
|
90
91
|
}
|
91
92
|
]
|
93
|
+
if parent
|
94
|
+
schema['links'] << {
|
95
|
+
"description" => "List existing #{resource}s for existing #{parent}.",
|
96
|
+
"href" => "/#{parent}s/{(%2Fschemata%2F#{parent}%23%2Fdefinitions%2Fidentity)}/#{resource}s",
|
97
|
+
"method" => "GET",
|
98
|
+
"rel" => "instances",
|
99
|
+
"title" => "List"
|
100
|
+
}
|
101
|
+
end
|
92
102
|
schema['properties'] = {
|
93
|
-
"created_at" => { "$ref" => "/
|
94
|
-
"id" => { "$ref" => "/
|
95
|
-
"updated_at" => { "$ref" => "/
|
103
|
+
"created_at" => { "$ref" => "/schemata/#{resource}#/definitions/created_at" },
|
104
|
+
"id" => { "$ref" => "/schemata/#{resource}#/definitions/id" },
|
105
|
+
"updated_at" => { "$ref" => "/schemata/#{resource}#/definitions/updated_at" }
|
96
106
|
}
|
97
107
|
end
|
98
108
|
|
data/lib/prmd/commands/verify.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
module Prmd
|
2
2
|
def self.verify(schema)
|
3
3
|
errors = []
|
4
|
+
errors << verify_schema(schema)
|
5
|
+
if schema['definitions']
|
6
|
+
schema['definitions'].each do |key, value|
|
7
|
+
errors << verify_schema(value)
|
8
|
+
errors << verify_definitions_and_links(value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
errors.flatten!
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.verify_schema(schema)
|
15
|
+
errors = []
|
4
16
|
|
5
17
|
id = schema['id']
|
6
18
|
|
7
19
|
missing_requirements = []
|
8
|
-
%w{
|
20
|
+
%w{$schema definitions description id links properties title type}.each do |requirement|
|
9
21
|
unless schema.has_key?(requirement)
|
10
22
|
missing_requirements << requirement
|
11
23
|
end
|
@@ -14,6 +26,14 @@ module Prmd
|
|
14
26
|
errors << "Missing `#{id}#/#{missing_requirement}`"
|
15
27
|
end
|
16
28
|
|
29
|
+
errors
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.verify_definitions_and_links(schema)
|
33
|
+
errors = []
|
34
|
+
|
35
|
+
id = schema['id']
|
36
|
+
|
17
37
|
if schema['definitions']
|
18
38
|
unless schema['definitions'].has_key?('identity')
|
19
39
|
errors << "Missing `#{id}#/definitions/identity`"
|
@@ -21,7 +41,7 @@ module Prmd
|
|
21
41
|
schema['definitions'].each do |key, value|
|
22
42
|
missing_requirements = []
|
23
43
|
unless key == 'identity'
|
24
|
-
%w{description
|
44
|
+
%w{description type}.each do |requirement|
|
25
45
|
unless schema['definitions'][key].has_key?(requirement)
|
26
46
|
missing_requirements << requirement
|
27
47
|
end
|
@@ -59,6 +79,8 @@ module Prmd
|
|
59
79
|
errors << "Missing #{missing_requirement} in `#{link}` link for `#{id}`"
|
60
80
|
end
|
61
81
|
end
|
82
|
+
else
|
83
|
+
errors << "Missing `#{id}/links`"
|
62
84
|
end
|
63
85
|
|
64
86
|
errors
|
data/lib/prmd/schema.rb
CHANGED
@@ -9,61 +9,13 @@ module Prmd
|
|
9
9
|
@data[key] = value
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.load(path, options={})
|
13
|
-
unless File.directory?(path)
|
14
|
-
data = JSON.parse(File.read(path))
|
15
|
-
else
|
16
|
-
data = {
|
17
|
-
'$schema' => 'http://json-schema.org/draft-04/hyper-schema',
|
18
|
-
'definitions' => {},
|
19
|
-
'properties' => {},
|
20
|
-
'type' => ['object']
|
21
|
-
}
|
22
|
-
|
23
|
-
if options[:meta] && File.exists?(options[:meta])
|
24
|
-
data.merge!(JSON.parse(File.read(options[:meta])))
|
25
|
-
end
|
26
|
-
|
27
|
-
Dir.glob(File.join(path, '**', '*.json')).each do |schema|
|
28
|
-
schema_data = JSON.parse(File.read(schema))
|
29
|
-
id = if schema_data['id']
|
30
|
-
schema_data['id'].gsub('schema/', '')
|
31
|
-
end
|
32
|
-
next if id.nil? || id[0..0] == '_' # FIXME: remove this exception?
|
33
|
-
|
34
|
-
data['definitions'][id] = schema_data
|
35
|
-
reference_localizer = lambda do |datum|
|
36
|
-
case datum
|
37
|
-
when Array
|
38
|
-
datum.map {|element| reference_localizer.call(element)}
|
39
|
-
when Hash
|
40
|
-
if datum.has_key?('$ref')
|
41
|
-
datum['$ref'] = datum['$ref'].gsub(%r{/schema/([^#]*)#}, '#/definitions/\1')
|
42
|
-
end
|
43
|
-
if datum.has_key?('href')
|
44
|
-
datum['href'] = datum['href'].gsub(%r{%2Fschema%2F([^%]*)%23%2F}, '%23%2Fdefinitions%2F\1%2F')
|
45
|
-
end
|
46
|
-
datum.each { |k,v| datum[k] = reference_localizer.call(v) }
|
47
|
-
else
|
48
|
-
datum
|
49
|
-
end
|
50
|
-
end
|
51
|
-
reference_localizer.call(data['definitions'][id])
|
52
|
-
|
53
|
-
data['properties'][id] = { '$ref' => "#/definitions/#{id}" }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
self.new(data)
|
58
|
-
end
|
59
|
-
|
60
12
|
def initialize(new_data = {})
|
61
13
|
convert_type_to_array = lambda do |datum|
|
62
14
|
case datum
|
63
15
|
when Array
|
64
16
|
datum.map { |element| convert_type_to_array.call(element) }
|
65
17
|
when Hash
|
66
|
-
if datum.has_key?('type')
|
18
|
+
if datum.has_key?('type') && datum['type'].is_a?(String)
|
67
19
|
datum['type'] = [*datum['type']]
|
68
20
|
end
|
69
21
|
datum.each { |k,v| datum[k] = convert_type_to_array.call(v) }
|
@@ -77,19 +29,26 @@ module Prmd
|
|
77
29
|
def dereference(reference)
|
78
30
|
if reference.is_a?(Hash)
|
79
31
|
if reference.has_key?('$ref')
|
80
|
-
|
32
|
+
value = reference.dup
|
33
|
+
key = value.delete('$ref')
|
81
34
|
else
|
82
|
-
return reference # no dereference needed
|
35
|
+
return [nil, reference] # no dereference needed
|
83
36
|
end
|
84
37
|
else
|
85
|
-
key = reference
|
38
|
+
key, value = reference, {}
|
86
39
|
end
|
87
40
|
begin
|
88
41
|
datum = @data
|
89
42
|
key.gsub(%r{[^#]*#/}, '').split('/').each do |fragment|
|
90
43
|
datum = datum[fragment]
|
91
44
|
end
|
92
|
-
|
45
|
+
# last dereference will have nil key, so compact it out
|
46
|
+
# [-2..-1] should be the final key reached before deref
|
47
|
+
dereferenced_key, dereferenced_value = dereference(datum)
|
48
|
+
[
|
49
|
+
[key, dereferenced_key].compact.last,
|
50
|
+
[dereferenced_value, value].inject({}) { |composite, element| composite.merge(element) }
|
51
|
+
]
|
93
52
|
rescue => error
|
94
53
|
$stderr.puts("Failed to dereference `#{key}`")
|
95
54
|
raise(error)
|
data/lib/prmd/version.rb
CHANGED
data/lib/prmd/views/endpoint.erb
CHANGED
@@ -24,8 +24,13 @@
|
|
24
24
|
<%- definition['links'].each do |link, datum| %>
|
25
25
|
<%- path = link['href'].gsub(%r|(\{\([^\)]+\)\})|) do |ref|
|
26
26
|
ref = ref.gsub('%2F', '/').gsub('%23', '#').gsub(%r|[\{\(\)\}]|, '')
|
27
|
-
resource = ref.
|
28
|
-
|
27
|
+
resource = ref.match(%r{^#/definitions/([^/]*)}).captures.first
|
28
|
+
identity_key, identity_value = schema.dereference(ref)
|
29
|
+
if identity_value.has_key?('anyOf')
|
30
|
+
'{' + resource + '_' + identity_value['anyOf'].map {|r| r['$ref'].split('/').last}.join('_or_') + '}'
|
31
|
+
else
|
32
|
+
'{' + resource + '_' + identity_key.split('/').last + '}'
|
33
|
+
end
|
29
34
|
end -%>
|
30
35
|
### <%= title %> <%= link['title'] %>
|
31
36
|
<%= link['description'] %>
|
@@ -53,31 +58,52 @@ end -%>
|
|
53
58
|
|
54
59
|
#### Curl Example
|
55
60
|
```term
|
56
|
-
|
57
|
-
|
58
|
-
<%-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
61
|
+
<%- path = path.gsub(/{([^}]*)}/) {|match| '$' + match.gsub(/[{}]/, '')} %>
|
62
|
+
<%- if link.has_key?('schema') && (link['schema'].has_key?('properties') || link['schema'].has_key?('example')) %>
|
63
|
+
<%-
|
64
|
+
data = {}
|
65
|
+
if link['schema']['properties']
|
66
|
+
link['schema']['properties'].each do |key, value|
|
67
|
+
if value.has_key?('anyOf')
|
68
|
+
id_ref = value['anyOf'].detect {|ref| ref['$ref'].split('/').last == 'id'}
|
69
|
+
data[key] = schema.dereference(id_ref).last['example']
|
70
|
+
elsif value.has_key?('properties')
|
71
|
+
data[key] = {}
|
72
|
+
value['properties'].each do |k,v|
|
73
|
+
data[key][k] = schema.dereference(v).last['example']
|
74
|
+
end
|
75
|
+
else
|
76
|
+
data[key] = schema.dereference(value).last['example']
|
69
77
|
end
|
70
|
-
else
|
71
|
-
data[key] = value['example']
|
72
78
|
end
|
79
|
+
else
|
80
|
+
data.merge!(link['schema']['example'])
|
73
81
|
end
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
82
|
+
%>
|
83
|
+
<%- if link['method'].upcase == 'GET' %>
|
84
|
+
<%-
|
85
|
+
unless data.empty?
|
86
|
+
path << '?'
|
87
|
+
data.sort_by {|k,_| k.to_s }.each do |key, values|
|
88
|
+
if values.nil?
|
89
|
+
path << key.to_s << '&'
|
90
|
+
else
|
91
|
+
[values].flatten.each do |value|
|
92
|
+
path << key.to_s << '=' << CGI.escape(value.to_s) << '&'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
path.chop! # remove trailing '&'
|
97
|
+
end
|
98
|
+
%>
|
99
|
+
$ curl -n -X <%= link['method'] %> <%= root_url %><%= path %>
|
100
|
+
<%- else %>
|
101
|
+
$ curl -n -X <%= link['method'] %> <%= root_url %><%= path %> \
|
102
|
+
-H "Content-Type: application/json" \
|
78
103
|
-d '<%= data.to_json %>'
|
104
|
+
<%- end %>
|
79
105
|
<%- else %>
|
80
|
-
|
106
|
+
$ curl -n -X <%= link['method'] %> <%= root_url %><%= path %>
|
81
107
|
<%- end %>
|
82
108
|
```
|
83
109
|
|
@@ -89,12 +115,6 @@ when 'create'
|
|
89
115
|
else
|
90
116
|
'200 OK'
|
91
117
|
end %>
|
92
|
-
<%- if link['rel'] == 'instances' && identifiers %>
|
93
|
-
Accept-Range: <%= identifiers.join(', ') %>
|
94
|
-
Content-Range: id 01234567-89ab-cdef-0123-456789abcdef..01234567-89ab-cdef-0123-456789abcdef; max=200
|
95
|
-
<%- end %>
|
96
|
-
ETag: "0123456789abcdef0123456789abcdef"
|
97
|
-
RateLimit-Remaining: 1200
|
98
118
|
```
|
99
119
|
```javascript```
|
100
120
|
<%- if link['rel'] == 'instances' %>
|
data/lib/prmd.rb
CHANGED
data/prmd.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Prmd::VERSION
|
9
9
|
spec.authors = ["geemus"]
|
10
10
|
spec.email = ["geemus@gmail.com"]
|
11
|
-
spec.description = %q{
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.homepage = ""
|
11
|
+
spec.description = %q{scaffold, verify and generate docs from JSON Schema}
|
12
|
+
spec.summary = %q{JSON Schema tooling}
|
13
|
+
spec.homepage = "https://github.com/heroku/prmd"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
@@ -18,10 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "
|
22
|
-
spec.add_dependency "erubis"
|
21
|
+
spec.add_dependency "erubis", "~> 2.7"
|
23
22
|
|
24
|
-
spec.add_development_dependency "bundler",
|
25
|
-
spec.add_development_dependency "rake"
|
26
|
-
spec.add_development_dependency "minitest"
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.2"
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.3"
|
27
26
|
end
|
data/test/helpers.rb
CHANGED
@@ -2,9 +2,9 @@ require "minitest/autorun"
|
|
2
2
|
require "prmd"
|
3
3
|
|
4
4
|
def input_schemas_path
|
5
|
-
|
5
|
+
@@data_path ||= File.join(File.dirname(__FILE__), 'schemas', 'input')
|
6
6
|
end
|
7
7
|
|
8
8
|
def user_input_schema
|
9
|
-
|
9
|
+
@@user_input_schema ||= Prmd.combine(File.join(input_schemas_path, 'user.json'))
|
10
10
|
end
|
data/test/schema_test.rb
CHANGED
@@ -1,13 +1,34 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'helpers')
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helpers'))
|
2
2
|
|
3
3
|
class SchemaTest < Minitest::Unit::TestCase
|
4
4
|
def test_dereference_with_ref
|
5
|
-
|
6
|
-
|
5
|
+
key, value = user_input_schema.dereference({
|
6
|
+
'$ref' => '#/definitions/user/definitions/id'
|
7
|
+
})
|
8
|
+
assert_equal(key, '#/definitions/user/definitions/id')
|
9
|
+
assert_equal(value, user_input_schema['definitions']['user']['definitions']['id'])
|
7
10
|
end
|
8
11
|
|
9
12
|
def test_dereference_without_ref
|
10
|
-
|
11
|
-
assert_equal
|
13
|
+
key, value = user_input_schema.dereference('#/definitions/user/definitions/id')
|
14
|
+
assert_equal(key, '#/definitions/user/definitions/id')
|
15
|
+
assert_equal(value, user_input_schema['definitions']['user']['definitions']['id'])
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_dereference_with_nested_ref
|
19
|
+
key, value = user_input_schema.dereference({
|
20
|
+
'$ref' => '#/definitions/user/definitions/identity'
|
21
|
+
})
|
22
|
+
assert_equal(key, '#/definitions/user/definitions/id')
|
23
|
+
assert_equal(value, user_input_schema['definitions']['user']['definitions']['id'])
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_dereference_with_local_context
|
27
|
+
key, value = user_input_schema.dereference({
|
28
|
+
'$ref' => '#/definitions/user/properties/id',
|
29
|
+
'override' => true
|
30
|
+
})
|
31
|
+
assert_equal(key, '#/definitions/user/definitions/id')
|
32
|
+
assert_equal(value, {'override' => true}.merge(user_input_schema['definitions']['user']['definitions']['id']))
|
12
33
|
end
|
13
34
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/hyper-schema",
|
3
|
+
"definitions": {},
|
4
|
+
"description": "API lets you interact with service",
|
5
|
+
"links": [{
|
6
|
+
"href": "https://api.example.com",
|
7
|
+
"rel": "self"
|
8
|
+
}],
|
9
|
+
"properties": {},
|
10
|
+
"title": "API",
|
11
|
+
"type": [
|
12
|
+
"object"
|
13
|
+
]
|
14
|
+
}
|
@@ -9,7 +9,6 @@
|
|
9
9
|
"description": "when user was created",
|
10
10
|
"example": "2012-01-01T12:00:00Z",
|
11
11
|
"format": "date-time",
|
12
|
-
"readOnly": true,
|
13
12
|
"type": [
|
14
13
|
"string"
|
15
14
|
]
|
@@ -18,19 +17,17 @@
|
|
18
17
|
"description": "unique identifier of user",
|
19
18
|
"example": "01234567-89ab-cdef-0123-456789abcdef",
|
20
19
|
"format": "uuid",
|
21
|
-
"readOnly": true,
|
22
20
|
"type": [
|
23
21
|
"string"
|
24
22
|
]
|
25
23
|
},
|
26
24
|
"identity": {
|
27
|
-
"$ref": "/
|
25
|
+
"$ref": "/schemata/user#/definitions/id"
|
28
26
|
},
|
29
27
|
"updated_at": {
|
30
28
|
"description": "when user was updated",
|
31
29
|
"example": "2012-01-01T12:00:00Z",
|
32
30
|
"format": "date-time",
|
33
|
-
"readOnly": true,
|
34
31
|
"type": [
|
35
32
|
"string"
|
36
33
|
]
|
@@ -53,14 +50,14 @@
|
|
53
50
|
},
|
54
51
|
{
|
55
52
|
"description": "Delete an existing user.",
|
56
|
-
"href": "/users/{(%
|
53
|
+
"href": "/users/{(%2Fschemata%2Fuser%23%2Fdefinitions%2Fidentity)}",
|
57
54
|
"method": "DELETE",
|
58
55
|
"rel": "destroy",
|
59
56
|
"title": "Delete"
|
60
57
|
},
|
61
58
|
{
|
62
59
|
"description": "Info for existing user.",
|
63
|
-
"href": "/users/{(%
|
60
|
+
"href": "/users/{(%2Fschemata%2Fuser%23%2Fdefinitions%2Fidentity)}",
|
64
61
|
"method": "GET",
|
65
62
|
"rel": "self",
|
66
63
|
"title": "Info"
|
@@ -74,7 +71,7 @@
|
|
74
71
|
},
|
75
72
|
{
|
76
73
|
"description": "Update an existing user.",
|
77
|
-
"href": "/users/{(%
|
74
|
+
"href": "/users/{(%2Fschemata%2Fuser%23%2Fdefinitions%2Fidentity)}",
|
78
75
|
"method": "PATCH",
|
79
76
|
"rel": "update",
|
80
77
|
"schema": {
|
@@ -89,14 +86,14 @@
|
|
89
86
|
],
|
90
87
|
"properties": {
|
91
88
|
"created_at": {
|
92
|
-
"$ref": "/
|
89
|
+
"$ref": "/schemata/user#/definitions/created_at"
|
93
90
|
},
|
94
91
|
"id": {
|
95
|
-
"$ref": "/
|
92
|
+
"$ref": "/schemata/user#/definitions/id"
|
96
93
|
},
|
97
94
|
"updated_at": {
|
98
|
-
"$ref": "/
|
95
|
+
"$ref": "/schemata/user#/definitions/updated_at"
|
99
96
|
}
|
100
97
|
},
|
101
|
-
"id": "
|
98
|
+
"id": "schemata/user"
|
102
99
|
}
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prmd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- geemus
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: diff-lcs
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ! '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ! '>='
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: erubis
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
|
-
- -
|
17
|
+
- - ~>
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
19
|
+
version: '2.7'
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
|
-
- -
|
24
|
+
- - ~>
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
26
|
+
version: '2.7'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: bundler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,31 +42,31 @@ dependencies:
|
|
56
42
|
name: rake
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
|
-
- -
|
45
|
+
- - ~>
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
47
|
+
version: '10.2'
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
|
-
- -
|
52
|
+
- - ~>
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
54
|
+
version: '10.2'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: minitest
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
|
-
- -
|
59
|
+
- - ~>
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
61
|
+
version: '5.3'
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
|
-
- -
|
66
|
+
- - ~>
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
83
|
-
description:
|
68
|
+
version: '5.3'
|
69
|
+
description: scaffold, verify and generate docs from JSON Schema
|
84
70
|
email:
|
85
71
|
- geemus@gmail.com
|
86
72
|
executables:
|
@@ -111,8 +97,9 @@ files:
|
|
111
97
|
- prmd.gemspec
|
112
98
|
- test/helpers.rb
|
113
99
|
- test/schema_test.rb
|
100
|
+
- test/schemas/input/meta.json
|
114
101
|
- test/schemas/input/user.json
|
115
|
-
homepage:
|
102
|
+
homepage: https://github.com/heroku/prmd
|
116
103
|
licenses:
|
117
104
|
- MIT
|
118
105
|
metadata: {}
|
@@ -135,9 +122,10 @@ rubyforge_project:
|
|
135
122
|
rubygems_version: 2.2.2
|
136
123
|
signing_key:
|
137
124
|
specification_version: 4
|
138
|
-
summary:
|
125
|
+
summary: JSON Schema tooling
|
139
126
|
test_files:
|
140
127
|
- test/helpers.rb
|
141
128
|
- test/schema_test.rb
|
129
|
+
- test/schemas/input/meta.json
|
142
130
|
- test/schemas/input/user.json
|
143
131
|
has_rdoc:
|