tomograph 2.4.2 → 2.5.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 +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +5 -0
- data/README.md +9 -1
- data/exe/tomograph +32 -6
- data/lib/tomograph/api_blueprint/crafter/yaml/action.rb +63 -0
- data/lib/tomograph/api_blueprint/crafter/yaml.rb +130 -0
- data/lib/tomograph/api_blueprint/drafter_3/yaml/action.rb +63 -0
- data/lib/tomograph/api_blueprint/drafter_3/yaml.rb +128 -0
- data/lib/tomograph/api_blueprint/drafter_4/yaml/action.rb +63 -0
- data/lib/tomograph/api_blueprint/drafter_4/yaml.rb +130 -0
- data/lib/tomograph/tomogram.rb +9 -3
- data/lib/tomograph/version.rb +1 -1
- metadata +9 -5
- data/lib/tomograph/api_blueprint/yaml/action.rb +0 -61
- data/lib/tomograph/api_blueprint/yaml.rb +0 -126
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 937a82ea94c38bdfbb1a92a6710936c7d525e228
|
4
|
+
data.tar.gz: 33cf0b7e2a4643acf32175e22c9ade017e3db49d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a88be0b668cce03d6c6b2a13fca948bc620cd92c21936de32189db078f1872fe67b1a63c7a3e93da3352d9eeee755583f2406aac92691e268676dff65b6ac050
|
7
|
+
data.tar.gz: 9d07f3e96dfd6ba0c7075682c048719072c2cb6c3df22754703de42371f3bc5c6bed63af18c069076f0d80ca47f82dc3221db3d8e4c45064ec0607d4e5954a4d
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.2.
|
1
|
+
2.2.10
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -38,11 +38,15 @@ The command line tool allows you to convert files from API Blueprint or API Elem
|
|
38
38
|
```
|
39
39
|
tomograph doc.apib doc.json
|
40
40
|
```
|
41
|
+
Now there is support for documents pre-parsed by [drafter](https://github.com/apiaryio/drafter) versions 3 and 4. To select the handler version, use the -d key and specify the required version. For example:
|
42
|
+
```
|
43
|
+
tomograph -d 4 doc_by_drafter4.yaml doc.json
|
44
|
+
```
|
41
45
|
See
|
42
46
|
```
|
43
47
|
tomograph -h
|
44
48
|
```
|
45
|
-
for details on usage.
|
49
|
+
for more details on usage.
|
46
50
|
|
47
51
|
## Convert
|
48
52
|
|
@@ -228,6 +232,10 @@ Path to API Blueprint documentation. There must be an installed [drafter](https:
|
|
228
232
|
|
229
233
|
Path to API Blueprint documentation pre-parsed with `drafter` and saved to a YAML file.
|
230
234
|
|
235
|
+
Drafter v.4
|
236
|
+
|
237
|
+
If you are using a `drafter v.4`, then you need to use the following parameters`drafter_4_apib_path` and `drafter_4_yaml_path` respectively.
|
238
|
+
|
231
239
|
### tomogram_json_path
|
232
240
|
|
233
241
|
Path to API Blueprint documentation converted with `tomograph` to a JSON file.
|
data/exe/tomograph
CHANGED
@@ -7,12 +7,12 @@ require 'methadone'
|
|
7
7
|
require 'tomograph'
|
8
8
|
require 'tomograph/version'
|
9
9
|
|
10
|
-
|
11
10
|
include Methadone::Main
|
12
11
|
include Methadone::CLILogging
|
13
12
|
|
14
13
|
version Tomograph::VERSION
|
15
14
|
description 'Converts API Blueprint to JSON Schema'
|
15
|
+
on('-d DRAFTER_VERSION', '--drafter', 'Choose drafter version: crafter, 3 or 4. Default: use drafter v.3.')
|
16
16
|
on('-f INPUT_FORMAT', '--format', 'Force input format: "apib" or "yaml". Default: detect by file extension.')
|
17
17
|
on('--exclude-description', 'Exclude "description" keys.')
|
18
18
|
on('--split', 'Split output into files by method.')
|
@@ -48,6 +48,21 @@ def guess_format(opt_format, input)
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
def choose_drafter(opt_parser)
|
52
|
+
case opt_parser
|
53
|
+
when 'crafter'
|
54
|
+
:crafter
|
55
|
+
when '3'
|
56
|
+
:drafter_3
|
57
|
+
when '4'
|
58
|
+
:drafter_4
|
59
|
+
when nil
|
60
|
+
:drafter_3
|
61
|
+
else
|
62
|
+
raise 'Unsupported drafter version!'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
51
66
|
def write_split_json(actions, output)
|
52
67
|
FileUtils.mkdir_p(output)
|
53
68
|
actions.clone.each do |action|
|
@@ -70,20 +85,31 @@ end
|
|
70
85
|
|
71
86
|
main do |input, output|
|
72
87
|
format = guess_format(options['format'], input)
|
88
|
+
version = choose_drafter(options['drafter'])
|
73
89
|
format_key = case format
|
74
90
|
when :apib
|
75
|
-
:
|
91
|
+
if version == :drafter_3
|
92
|
+
:apib_path
|
93
|
+
elsif version == :crafter
|
94
|
+
:crafter_apib_path
|
95
|
+
else
|
96
|
+
:drafter_4_apib_path
|
97
|
+
end
|
76
98
|
when :yaml
|
77
|
-
:
|
99
|
+
if version == :drafter_3
|
100
|
+
:drafter_yaml_path
|
101
|
+
elsif version == :crafter
|
102
|
+
:crafter_yaml_path
|
103
|
+
else
|
104
|
+
:drafter_4_yaml_path
|
105
|
+
end
|
78
106
|
else
|
79
107
|
fail NotImplementedError
|
80
108
|
end
|
81
109
|
tomogram = Tomograph::Tomogram.new(format_key => input)
|
82
110
|
actions = tomogram.to_a.map(&:to_hash)
|
83
111
|
|
84
|
-
if options['exclude-description']
|
85
|
-
prune!(actions, 'description')
|
86
|
-
end
|
112
|
+
prune!(actions, 'description') if options['exclude-description']
|
87
113
|
|
88
114
|
if options['split']
|
89
115
|
write_split_json(actions, output)
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'tomograph/tomogram/action'
|
2
|
+
|
3
|
+
module Tomograph
|
4
|
+
module ApiBlueprint
|
5
|
+
class Crafter
|
6
|
+
class Yaml
|
7
|
+
class Action
|
8
|
+
def initialize(content, path, resource)
|
9
|
+
@content = content
|
10
|
+
@path = path
|
11
|
+
@resource = resource
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :path, :resource
|
15
|
+
|
16
|
+
def method
|
17
|
+
@method ||= @content.first['attributes']['method']['content']
|
18
|
+
end
|
19
|
+
|
20
|
+
def content_type
|
21
|
+
@content_type ||= @content.first['attributes'].has_key?('headers') ?
|
22
|
+
@content.first['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def request
|
26
|
+
return @request if @request
|
27
|
+
|
28
|
+
request_action = @content.find { |el| el['element'] == 'httpRequest' }
|
29
|
+
@request = json_schema(request_action['content'])
|
30
|
+
end
|
31
|
+
|
32
|
+
def json_schema(actions)
|
33
|
+
schema_node = actions.find do |action|
|
34
|
+
action && action['element'] == 'asset' && action['attributes']['contentType']['content'] == 'application/schema+json'
|
35
|
+
end
|
36
|
+
return {} unless schema_node
|
37
|
+
|
38
|
+
MultiJson.load(schema_node['content'])
|
39
|
+
rescue MultiJson::ParseError => e
|
40
|
+
puts "[Tomograph] Error while parsing #{e}. skipping..."
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
|
44
|
+
def responses
|
45
|
+
return @responses if @responses
|
46
|
+
|
47
|
+
@responses = @content.select do |response|
|
48
|
+
response['element'] == 'httpResponse' && response['attributes']
|
49
|
+
end
|
50
|
+
@responses = @responses.map do |response|
|
51
|
+
{
|
52
|
+
'status' => response['attributes']['statusCode']['content'],
|
53
|
+
'body' => json_schema(response['content']),
|
54
|
+
'content-type' => response['attributes'].has_key?('headers') ?
|
55
|
+
response['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'tomograph/api_blueprint/crafter/yaml/action'
|
3
|
+
require 'tomograph/tomogram/action'
|
4
|
+
|
5
|
+
module Tomograph
|
6
|
+
module ApiBlueprint
|
7
|
+
class Crafter
|
8
|
+
class Yaml
|
9
|
+
def initialize(prefix, apib_path, drafter_yaml_path)
|
10
|
+
@prefix = prefix
|
11
|
+
@documentation = if apib_path
|
12
|
+
YAML.safe_load(`drafter #{apib_path}`)
|
13
|
+
elsif drafter_yaml_path
|
14
|
+
YAML.safe_load(File.read(drafter_yaml_path))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def groups
|
19
|
+
@groups ||= @documentation['content'][0]['content'].each_with_object([]) do |group, result_groups|
|
20
|
+
result_groups.push(group) if group?(group)
|
21
|
+
result_groups.push('content' => [group]) if single_resource?(group)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def single_resource?(group)
|
26
|
+
group['element'] == 'resource'
|
27
|
+
end
|
28
|
+
|
29
|
+
def group?(group)
|
30
|
+
return false if group['element'] == 'resource'
|
31
|
+
group['element'] != 'copy' && # Element is a human readable text
|
32
|
+
group['meta']['classes'][0] == 'resourceGroup' # skip Data Structures
|
33
|
+
end
|
34
|
+
|
35
|
+
def resources
|
36
|
+
@resources ||= groups.inject([]) do |result_groups, group|
|
37
|
+
result_groups.push(group['content'].each_with_object([]) do |resource, result_resources|
|
38
|
+
result_resources.push('resource' => resource, 'resource_path' => resource_path(resource)) if resource?(resource)
|
39
|
+
end)
|
40
|
+
end.flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
def resource?(resource)
|
44
|
+
resource['element'] != 'copy' # Element is a human readable text
|
45
|
+
end
|
46
|
+
|
47
|
+
def resource_path(resource)
|
48
|
+
resource['attributes'] && resource['attributes']['href']['content']
|
49
|
+
end
|
50
|
+
|
51
|
+
def transitions
|
52
|
+
@transitions ||= resources.inject([]) do |result_resources, resource|
|
53
|
+
result_resources.push(resource['resource']['content'].each_with_object([]) do |transition, result_transitions|
|
54
|
+
result_transitions.push(transition_hash(transition, resource)) if transition?(transition)
|
55
|
+
end)
|
56
|
+
end.flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
def transition?(transition)
|
60
|
+
transition['element'] == 'transition'
|
61
|
+
end
|
62
|
+
|
63
|
+
def transition_hash(transition, resource)
|
64
|
+
{
|
65
|
+
'transition' => transition,
|
66
|
+
'transition_path' => transition_path(transition, resource['resource_path']),
|
67
|
+
'resource' => resource['resource_path']
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def transition_path(transition, resource_path)
|
72
|
+
transition['attributes'] && transition['attributes']['href'] && transition['attributes']['href']['content'] || resource_path
|
73
|
+
end
|
74
|
+
|
75
|
+
def without_group_actions
|
76
|
+
transitions.inject([]) do |result_transition, transition|
|
77
|
+
result_transition.push(transition['transition']['content'].each_with_object([]) do |content, result_contents|
|
78
|
+
result_contents.push(Tomograph::ApiBlueprint::Crafter::Yaml::Action.new(
|
79
|
+
content['content'],
|
80
|
+
transition['transition_path'],
|
81
|
+
transition['resource']
|
82
|
+
)) if action?(content)
|
83
|
+
end)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def action?(content)
|
88
|
+
content['element'] == 'httpTransaction'
|
89
|
+
end
|
90
|
+
|
91
|
+
def actions
|
92
|
+
@actions ||= without_group_actions
|
93
|
+
.flatten
|
94
|
+
.group_by { |action| "#{action.method} #{action.path}" }.map do |_key, related_actions|
|
95
|
+
action_hash(related_actions)
|
96
|
+
end.flatten
|
97
|
+
end
|
98
|
+
|
99
|
+
def action_hash(related_actions)
|
100
|
+
{
|
101
|
+
path: "#{@prefix}#{related_actions.first.path}",
|
102
|
+
method: related_actions.first.method,
|
103
|
+
content_type: related_actions.first.content_type,
|
104
|
+
request: related_actions.first.request,
|
105
|
+
responses: related_actions.map(&:responses).flatten,
|
106
|
+
resource: related_actions.first.resource
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_tomogram
|
111
|
+
@tomogram ||= actions.inject([]) do |result, action|
|
112
|
+
result.push(Tomograph::Tomogram::Action.new(action))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_resources
|
117
|
+
return @to_resources if @to_resources
|
118
|
+
|
119
|
+
@to_resources = actions.group_by { |action| action[:resource] }
|
120
|
+
@to_resources = @to_resources.inject({}) do |res, related_actions|
|
121
|
+
requests = related_actions[1].map do |action|
|
122
|
+
"#{action[:method]} #{action[:path]}"
|
123
|
+
end
|
124
|
+
res.merge(related_actions[1].first[:resource] => requests)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'tomograph/tomogram/action'
|
2
|
+
|
3
|
+
module Tomograph
|
4
|
+
module ApiBlueprint
|
5
|
+
class Drafter3
|
6
|
+
class Yaml
|
7
|
+
class Action
|
8
|
+
def initialize(content, path, resource)
|
9
|
+
@content = content
|
10
|
+
@path = path
|
11
|
+
@resource = resource
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :path, :resource
|
15
|
+
|
16
|
+
def method
|
17
|
+
@method ||= @content.first['attributes']['method']
|
18
|
+
end
|
19
|
+
|
20
|
+
def content_type
|
21
|
+
@content_type ||= @content.first['attributes'].has_key?('headers') ?
|
22
|
+
@content.first['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def request
|
26
|
+
return @request if @request
|
27
|
+
|
28
|
+
request_action = @content.find { |el| el['element'] == 'httpRequest' }
|
29
|
+
@request = json_schema(request_action['content'])
|
30
|
+
end
|
31
|
+
|
32
|
+
def json_schema(actions)
|
33
|
+
schema_node = actions.find do |action|
|
34
|
+
action && action['element'] == 'asset' && action['attributes']['contentType'] == 'application/schema+json'
|
35
|
+
end
|
36
|
+
return {} unless schema_node
|
37
|
+
|
38
|
+
MultiJson.load(schema_node['content'])
|
39
|
+
rescue MultiJson::ParseError => e
|
40
|
+
puts "[Tomograph] Error while parsing #{e}. skipping..."
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
|
44
|
+
def responses
|
45
|
+
return @responses if @responses
|
46
|
+
|
47
|
+
@responses = @content.select do |response|
|
48
|
+
response['element'] == 'httpResponse' && response['attributes']
|
49
|
+
end
|
50
|
+
@responses = @responses.map do |response|
|
51
|
+
{
|
52
|
+
'status' => response['attributes']['statusCode'],
|
53
|
+
'body' => json_schema(response['content']),
|
54
|
+
'content-type' => response['attributes'].has_key?('headers') ?
|
55
|
+
response['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'tomograph/api_blueprint/drafter_3/yaml/action'
|
3
|
+
require 'tomograph/tomogram/action'
|
4
|
+
|
5
|
+
module Tomograph
|
6
|
+
module ApiBlueprint
|
7
|
+
class Drafter3
|
8
|
+
class Yaml
|
9
|
+
def initialize(prefix, apib_path, drafter_yaml_path)
|
10
|
+
@prefix = prefix
|
11
|
+
@documentation = if apib_path
|
12
|
+
YAML.safe_load(`drafter #{apib_path}`)
|
13
|
+
elsif drafter_yaml_path
|
14
|
+
YAML.safe_load(File.read(drafter_yaml_path))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def groups
|
19
|
+
@groups ||= @documentation['content'][0]['content'].inject([]) do |result_groups, group|
|
20
|
+
next result_groups unless group?(group)
|
21
|
+
result_groups.push(group)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def group?(group)
|
26
|
+
group['element'] != 'copy' && # Element is a human readable text
|
27
|
+
group['meta']['classes'][0] == 'resourceGroup' # skip Data Structures
|
28
|
+
end
|
29
|
+
|
30
|
+
def resources
|
31
|
+
@resources ||= groups.inject([]) do |result_groups, group|
|
32
|
+
result_groups.push(group['content'].inject([]) do |result_resources, resource|
|
33
|
+
next result_resources unless resource?(resource)
|
34
|
+
result_resources.push('resource' => resource, 'resource_path' => resource_path(resource))
|
35
|
+
end)
|
36
|
+
end.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def resource?(resource)
|
40
|
+
resource['element'] != 'copy' # Element is a human readable text
|
41
|
+
end
|
42
|
+
|
43
|
+
def resource_path(resource)
|
44
|
+
resource['attributes'] && resource['attributes']['href']
|
45
|
+
end
|
46
|
+
|
47
|
+
def transitions
|
48
|
+
@transitions ||= resources.inject([]) do |result_resources, resource|
|
49
|
+
result_resources.push(resource['resource']['content'].inject([]) do |result_transitions, transition|
|
50
|
+
next result_transitions unless transition?(transition)
|
51
|
+
result_transitions.push(transition_hash(transition, resource))
|
52
|
+
end)
|
53
|
+
end.flatten
|
54
|
+
end
|
55
|
+
|
56
|
+
def transition?(transition)
|
57
|
+
transition['element'] == 'transition'
|
58
|
+
end
|
59
|
+
|
60
|
+
def transition_hash(transition, resource)
|
61
|
+
{
|
62
|
+
'transition' => transition,
|
63
|
+
'transition_path' => transition_path(transition, resource['resource_path']),
|
64
|
+
'resource' => resource['resource_path']
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def transition_path(transition, resource_path)
|
69
|
+
transition['attributes'] && transition['attributes']['href'] || resource_path
|
70
|
+
end
|
71
|
+
|
72
|
+
def without_group_actions
|
73
|
+
transitions.inject([]) do |result_transition, transition|
|
74
|
+
result_transition.push(transition['transition']['content'].inject([]) do |result_contents, content|
|
75
|
+
next result_contents unless action?(content)
|
76
|
+
result_contents.push(Tomograph::ApiBlueprint::Drafter3::Yaml::Action.new(
|
77
|
+
content['content'],
|
78
|
+
transition['transition_path'],
|
79
|
+
transition['resource']
|
80
|
+
))
|
81
|
+
end)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def action?(content)
|
86
|
+
content['element'] == 'httpTransaction'
|
87
|
+
end
|
88
|
+
|
89
|
+
def actions
|
90
|
+
@actions ||= without_group_actions
|
91
|
+
.flatten
|
92
|
+
.group_by { |action| "#{action.method} #{action.path}" }.map do |_key, related_actions|
|
93
|
+
action_hash(related_actions)
|
94
|
+
end.flatten
|
95
|
+
end
|
96
|
+
|
97
|
+
def action_hash(related_actions)
|
98
|
+
{
|
99
|
+
path: "#{@prefix}#{related_actions.first.path}",
|
100
|
+
method: related_actions.first.method,
|
101
|
+
content_type: related_actions.first.content_type,
|
102
|
+
request: related_actions.first.request,
|
103
|
+
responses: related_actions.map(&:responses).flatten,
|
104
|
+
resource: related_actions.first.resource
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_tomogram
|
109
|
+
@tomogram ||= actions.inject([]) do |result, action|
|
110
|
+
result.push(Tomograph::Tomogram::Action.new(action))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_resources
|
115
|
+
return @to_resources if @to_resources
|
116
|
+
|
117
|
+
@to_resources = actions.group_by { |action| action[:resource] }
|
118
|
+
@to_resources = @to_resources.inject({}) do |res, related_actions|
|
119
|
+
requests = related_actions[1].map do |action|
|
120
|
+
"#{action[:method]} #{action[:path]}"
|
121
|
+
end
|
122
|
+
res.merge(related_actions[1].first[:resource] => requests)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'tomograph/tomogram/action'
|
2
|
+
|
3
|
+
module Tomograph
|
4
|
+
module ApiBlueprint
|
5
|
+
class Drafter4
|
6
|
+
class Yaml
|
7
|
+
class Action
|
8
|
+
def initialize(content, path, resource)
|
9
|
+
@content = content
|
10
|
+
@path = path
|
11
|
+
@resource = resource
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :path, :resource
|
15
|
+
|
16
|
+
def method
|
17
|
+
@method ||= @content.first['attributes']['method']['content']
|
18
|
+
end
|
19
|
+
|
20
|
+
def content_type
|
21
|
+
@content_type ||= @content.first['attributes'].has_key?('headers') ?
|
22
|
+
@content.first['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def request
|
26
|
+
return @request if @request
|
27
|
+
|
28
|
+
request_action = @content.find { |el| el['element'] == 'httpRequest' }
|
29
|
+
@request = json_schema(request_action['content'])
|
30
|
+
end
|
31
|
+
|
32
|
+
def json_schema(actions)
|
33
|
+
schema_node = actions.find do |action|
|
34
|
+
action && action['element'] == 'asset' && action['attributes']['contentType']['content'] == 'application/schema+json'
|
35
|
+
end
|
36
|
+
return {} unless schema_node
|
37
|
+
|
38
|
+
MultiJson.load(schema_node['content'])
|
39
|
+
rescue MultiJson::ParseError => e
|
40
|
+
puts "[Tomograph] Error while parsing #{e}. skipping..."
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
|
44
|
+
def responses
|
45
|
+
return @responses if @responses
|
46
|
+
|
47
|
+
@responses = @content.select do |response|
|
48
|
+
response['element'] == 'httpResponse' && response['attributes']
|
49
|
+
end
|
50
|
+
@responses = @responses.map do |response|
|
51
|
+
{
|
52
|
+
'status' => response['attributes']['statusCode']['content'],
|
53
|
+
'body' => json_schema(response['content']),
|
54
|
+
'content-type' => response['attributes'].has_key?('headers') ?
|
55
|
+
response['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'tomograph/api_blueprint/drafter_4/yaml/action'
|
3
|
+
require 'tomograph/tomogram/action'
|
4
|
+
|
5
|
+
module Tomograph
|
6
|
+
module ApiBlueprint
|
7
|
+
class Drafter4
|
8
|
+
class Yaml
|
9
|
+
def initialize(prefix, apib_path, drafter_yaml_path)
|
10
|
+
@prefix = prefix
|
11
|
+
@documentation = if apib_path
|
12
|
+
YAML.safe_load(`drafter #{apib_path}`)
|
13
|
+
elsif drafter_yaml_path
|
14
|
+
YAML.safe_load(File.read(drafter_yaml_path))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def groups
|
19
|
+
@groups ||= @documentation['content'][0]['content'].each_with_object([]) do |group, result_groups|
|
20
|
+
result_groups.push(group) if group?(group)
|
21
|
+
result_groups.push('content' => [group]) if single_resource?(group)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def single_resource?(group)
|
26
|
+
group['element'] == 'resource'
|
27
|
+
end
|
28
|
+
|
29
|
+
def group?(group)
|
30
|
+
return false if group['element'] == 'resource'
|
31
|
+
group['element'] != 'copy' && # Element is a human readable text
|
32
|
+
group['meta']['classes']['content'][0]['content'] == 'resourceGroup' # skip Data Structures
|
33
|
+
end
|
34
|
+
|
35
|
+
def resources
|
36
|
+
@resources ||= groups.inject([]) do |result_groups, group|
|
37
|
+
result_groups.push(group['content'].each_with_object([]) do |resource, result_resources|
|
38
|
+
result_resources.push('resource' => resource, 'resource_path' => resource_path(resource)) if resource?(resource)
|
39
|
+
end)
|
40
|
+
end.flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
def resource?(resource)
|
44
|
+
resource['element'] != 'copy' # Element is a human readable text
|
45
|
+
end
|
46
|
+
|
47
|
+
def resource_path(resource)
|
48
|
+
resource['attributes'] && resource['attributes']['href']['content']
|
49
|
+
end
|
50
|
+
|
51
|
+
def transitions
|
52
|
+
@transitions ||= resources.inject([]) do |result_resources, resource|
|
53
|
+
result_resources.push(resource['resource']['content'].each_with_object([]) do |transition, result_transitions|
|
54
|
+
result_transitions.push(transition_hash(transition, resource)) if transition?(transition)
|
55
|
+
end)
|
56
|
+
end.flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
def transition?(transition)
|
60
|
+
transition['element'] == 'transition'
|
61
|
+
end
|
62
|
+
|
63
|
+
def transition_hash(transition, resource)
|
64
|
+
{
|
65
|
+
'transition' => transition,
|
66
|
+
'transition_path' => transition_path(transition, resource['resource_path']),
|
67
|
+
'resource' => resource['resource_path']
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def transition_path(transition, resource_path)
|
72
|
+
transition['attributes'] && transition['attributes']['href']['content'] || resource_path
|
73
|
+
end
|
74
|
+
|
75
|
+
def without_group_actions
|
76
|
+
transitions.inject([]) do |result_transition, transition|
|
77
|
+
result_transition.push(transition['transition']['content'].each_with_object([]) do |content, result_contents|
|
78
|
+
result_contents.push(Tomograph::ApiBlueprint::Drafter4::Yaml::Action.new(
|
79
|
+
content['content'],
|
80
|
+
transition['transition_path'],
|
81
|
+
transition['resource']
|
82
|
+
)) if action?(content)
|
83
|
+
end)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def action?(content)
|
88
|
+
content['element'] == 'httpTransaction'
|
89
|
+
end
|
90
|
+
|
91
|
+
def actions
|
92
|
+
@actions ||= without_group_actions
|
93
|
+
.flatten
|
94
|
+
.group_by { |action| "#{action.method} #{action.path}" }.map do |_key, related_actions|
|
95
|
+
action_hash(related_actions)
|
96
|
+
end.flatten
|
97
|
+
end
|
98
|
+
|
99
|
+
def action_hash(related_actions)
|
100
|
+
{
|
101
|
+
path: "#{@prefix}#{related_actions.first.path}",
|
102
|
+
method: related_actions.first.method,
|
103
|
+
content_type: related_actions.first.content_type,
|
104
|
+
request: related_actions.first.request,
|
105
|
+
responses: related_actions.map(&:responses).flatten,
|
106
|
+
resource: related_actions.first.resource
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
def to_tomogram
|
111
|
+
@tomogram ||= actions.inject([]) do |result, action|
|
112
|
+
result.push(Tomograph::Tomogram::Action.new(action))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_resources
|
117
|
+
return @to_resources if @to_resources
|
118
|
+
|
119
|
+
@to_resources = actions.group_by { |action| action[:resource] }
|
120
|
+
@to_resources = @to_resources.inject({}) do |res, related_actions|
|
121
|
+
requests = related_actions[1].map do |action|
|
122
|
+
"#{action[:method]} #{action[:path]}"
|
123
|
+
end
|
124
|
+
res.merge(related_actions[1].first[:resource] => requests)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/tomograph/tomogram.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
require 'multi_json'
|
2
2
|
require 'tomograph/path'
|
3
3
|
require 'tomograph/api_blueprint/json_schema'
|
4
|
-
require 'tomograph/api_blueprint/yaml'
|
4
|
+
require 'tomograph/api_blueprint/drafter_3/yaml'
|
5
|
+
require 'tomograph/api_blueprint/drafter_4/yaml'
|
6
|
+
require 'tomograph/api_blueprint/crafter/yaml'
|
5
7
|
|
6
8
|
module Tomograph
|
7
9
|
class Tomogram
|
8
10
|
extend Gem::Deprecate
|
9
11
|
|
10
|
-
def initialize(prefix: '', apib_path: nil, drafter_yaml_path: nil, tomogram_json_path: nil)
|
12
|
+
def initialize(prefix: '', apib_path: nil, drafter_yaml_path: nil, tomogram_json_path: nil, drafter_4_apib_path: nil, drafter_4_yaml_path: nil, crafter_apib_path: nil, crafter_yaml_path: nil)
|
11
13
|
@documentation = if tomogram_json_path
|
12
14
|
Tomograph::ApiBlueprint::JsonSchema.new(prefix, tomogram_json_path)
|
15
|
+
elsif drafter_4_yaml_path || drafter_4_apib_path
|
16
|
+
Tomograph::ApiBlueprint::Drafter4::Yaml.new(prefix, drafter_4_apib_path, drafter_4_yaml_path)
|
17
|
+
elsif crafter_yaml_path || crafter_apib_path
|
18
|
+
Tomograph::ApiBlueprint::Crafter::Yaml.new(prefix, crafter_apib_path, crafter_yaml_path)
|
13
19
|
else
|
14
|
-
Tomograph::ApiBlueprint::Yaml.new(prefix, apib_path, drafter_yaml_path)
|
20
|
+
Tomograph::ApiBlueprint::Drafter3::Yaml.new(prefix, apib_path, drafter_yaml_path)
|
15
21
|
end
|
16
22
|
@prefix = prefix
|
17
23
|
end
|
data/lib/tomograph/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tomograph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- d.efimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: methadone
|
@@ -180,9 +180,13 @@ files:
|
|
180
180
|
- bin/setup
|
181
181
|
- exe/tomograph
|
182
182
|
- lib/tomograph.rb
|
183
|
+
- lib/tomograph/api_blueprint/crafter/yaml.rb
|
184
|
+
- lib/tomograph/api_blueprint/crafter/yaml/action.rb
|
185
|
+
- lib/tomograph/api_blueprint/drafter_3/yaml.rb
|
186
|
+
- lib/tomograph/api_blueprint/drafter_3/yaml/action.rb
|
187
|
+
- lib/tomograph/api_blueprint/drafter_4/yaml.rb
|
188
|
+
- lib/tomograph/api_blueprint/drafter_4/yaml/action.rb
|
183
189
|
- lib/tomograph/api_blueprint/json_schema.rb
|
184
|
-
- lib/tomograph/api_blueprint/yaml.rb
|
185
|
-
- lib/tomograph/api_blueprint/yaml/action.rb
|
186
190
|
- lib/tomograph/path.rb
|
187
191
|
- lib/tomograph/tomogram.rb
|
188
192
|
- lib/tomograph/tomogram/action.rb
|
@@ -209,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
213
|
version: '0'
|
210
214
|
requirements: []
|
211
215
|
rubyforge_project:
|
212
|
-
rubygems_version: 2.4.5
|
216
|
+
rubygems_version: 2.4.5.5
|
213
217
|
signing_key:
|
214
218
|
specification_version: 4
|
215
219
|
summary: Convert API Blueprint to Tomogram
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'tomograph/tomogram/action'
|
2
|
-
|
3
|
-
module Tomograph
|
4
|
-
module ApiBlueprint
|
5
|
-
class Yaml
|
6
|
-
class Action
|
7
|
-
def initialize(content, path, resource)
|
8
|
-
@content = content
|
9
|
-
@path = path
|
10
|
-
@resource = resource
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :path, :resource
|
14
|
-
|
15
|
-
def method
|
16
|
-
@method ||= @content.first['attributes']['method']
|
17
|
-
end
|
18
|
-
|
19
|
-
def content_type
|
20
|
-
@content_type ||= @content.first['attributes'].has_key?('headers') ?
|
21
|
-
@content.first['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
22
|
-
end
|
23
|
-
|
24
|
-
def request
|
25
|
-
return @request if @request
|
26
|
-
|
27
|
-
request_action = @content.find { |el| el['element'] == 'httpRequest' }
|
28
|
-
@request = json_schema(request_action['content'])
|
29
|
-
end
|
30
|
-
|
31
|
-
def json_schema(actions)
|
32
|
-
schema_node = actions.find do |action|
|
33
|
-
action && action['element'] == 'asset' && action['attributes']['contentType'] == 'application/schema+json'
|
34
|
-
end
|
35
|
-
return {} unless schema_node
|
36
|
-
|
37
|
-
MultiJson.load(schema_node['content'])
|
38
|
-
rescue MultiJson::ParseError => e
|
39
|
-
puts "[Tomograph] Error while parsing #{e}. skipping..."
|
40
|
-
{}
|
41
|
-
end
|
42
|
-
|
43
|
-
def responses
|
44
|
-
return @responses if @responses
|
45
|
-
|
46
|
-
@responses = @content.select do |response|
|
47
|
-
response['element'] == 'httpResponse' && response['attributes']
|
48
|
-
end
|
49
|
-
@responses = @responses.map do |response|
|
50
|
-
{
|
51
|
-
'status' => response['attributes']['statusCode'],
|
52
|
-
'body' => json_schema(response['content']),
|
53
|
-
'content-type' => response['attributes'].has_key?('headers') ?
|
54
|
-
response['attributes']['headers']['content'][0]['content']['value']['content'] : nil
|
55
|
-
}
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'tomograph/api_blueprint/yaml/action'
|
3
|
-
require 'tomograph/tomogram/action'
|
4
|
-
|
5
|
-
module Tomograph
|
6
|
-
module ApiBlueprint
|
7
|
-
class Yaml
|
8
|
-
def initialize(prefix, apib_path, drafter_yaml_path)
|
9
|
-
@prefix = prefix
|
10
|
-
@documentation = if apib_path
|
11
|
-
YAML.safe_load(`drafter #{apib_path}`)
|
12
|
-
elsif drafter_yaml_path
|
13
|
-
YAML.safe_load(File.read(drafter_yaml_path))
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def groups
|
18
|
-
@groups ||= @documentation['content'][0]['content'].inject([]) do |result_groups, group|
|
19
|
-
next result_groups unless group?(group)
|
20
|
-
result_groups.push(group)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def group?(group)
|
25
|
-
group['element'] != 'copy' && # Element is a human readable text
|
26
|
-
group['meta']['classes'][0] == 'resourceGroup' # skip Data Structures
|
27
|
-
end
|
28
|
-
|
29
|
-
def resources
|
30
|
-
@resources ||= groups.inject([]) do |result_groups, group|
|
31
|
-
result_groups.push(group['content'].inject([]) do |result_resources, resource|
|
32
|
-
next result_resources unless resource?(resource)
|
33
|
-
result_resources.push('resource' => resource, 'resource_path' => resource_path(resource))
|
34
|
-
end)
|
35
|
-
end.flatten
|
36
|
-
end
|
37
|
-
|
38
|
-
def resource?(resource)
|
39
|
-
resource['element'] != 'copy' # Element is a human readable text
|
40
|
-
end
|
41
|
-
|
42
|
-
def resource_path(resource)
|
43
|
-
resource['attributes'] && resource['attributes']['href']
|
44
|
-
end
|
45
|
-
|
46
|
-
def transitions
|
47
|
-
@transitions ||= resources.inject([]) do |result_resources, resource|
|
48
|
-
result_resources.push(resource['resource']['content'].inject([]) do |result_transitions, transition|
|
49
|
-
next result_transitions unless transition?(transition)
|
50
|
-
result_transitions.push(transition_hash(transition, resource))
|
51
|
-
end)
|
52
|
-
end.flatten
|
53
|
-
end
|
54
|
-
|
55
|
-
def transition?(transition)
|
56
|
-
transition['element'] == 'transition'
|
57
|
-
end
|
58
|
-
|
59
|
-
def transition_hash(transition, resource)
|
60
|
-
{
|
61
|
-
'transition' => transition,
|
62
|
-
'transition_path' => transition_path(transition, resource['resource_path']),
|
63
|
-
'resource' => resource['resource_path']
|
64
|
-
}
|
65
|
-
end
|
66
|
-
|
67
|
-
def transition_path(transition, resource_path)
|
68
|
-
transition['attributes'] && transition['attributes']['href'] || resource_path
|
69
|
-
end
|
70
|
-
|
71
|
-
def without_group_actions
|
72
|
-
transitions.inject([]) do |result_transition, transition|
|
73
|
-
result_transition.push(transition['transition']['content'].inject([]) do |result_contents, content|
|
74
|
-
next result_contents unless action?(content)
|
75
|
-
result_contents.push(Tomograph::ApiBlueprint::Yaml::Action.new(
|
76
|
-
content['content'],
|
77
|
-
transition['transition_path'],
|
78
|
-
transition['resource']
|
79
|
-
))
|
80
|
-
end)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def action?(content)
|
85
|
-
content['element'] == 'httpTransaction'
|
86
|
-
end
|
87
|
-
|
88
|
-
def actions
|
89
|
-
@actions ||= without_group_actions
|
90
|
-
.flatten
|
91
|
-
.group_by { |action| "#{action.method} #{action.path}" }.map do |_key, related_actions|
|
92
|
-
action_hash(related_actions)
|
93
|
-
end.flatten
|
94
|
-
end
|
95
|
-
|
96
|
-
def action_hash(related_actions)
|
97
|
-
{
|
98
|
-
path: "#{@prefix}#{related_actions.first.path}",
|
99
|
-
method: related_actions.first.method,
|
100
|
-
content_type: related_actions.first.content_type,
|
101
|
-
request: related_actions.first.request,
|
102
|
-
responses: related_actions.map(&:responses).flatten,
|
103
|
-
resource: related_actions.first.resource
|
104
|
-
}
|
105
|
-
end
|
106
|
-
|
107
|
-
def to_tomogram
|
108
|
-
@tomogram ||= actions.inject([]) do |result, action|
|
109
|
-
result.push(Tomograph::Tomogram::Action.new(action))
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def to_resources
|
114
|
-
return @to_resources if @to_resources
|
115
|
-
|
116
|
-
@to_resources = actions.group_by { |action| action[:resource] }
|
117
|
-
@to_resources = @to_resources.inject({}) do |res, related_actions|
|
118
|
-
requests = related_actions[1].map do |action|
|
119
|
-
"#{action[:method]} #{action[:path]}"
|
120
|
-
end
|
121
|
-
res.merge(related_actions[1].first[:resource] => requests)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|