minimum-term 0.2.0 → 0.2.1
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/README.markdown +32 -27
- data/circle.yml +0 -2
- data/lib/minimum-term/conversion.rb +24 -17
- data/lib/minimum-term/conversion/data_structure.rb +15 -16
- data/lib/minimum-term/version.rb +1 -1
- data/minimum-term.gemspec +3 -1
- metadata +33 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30209807ad2ee5a4eaf45521202334f1eca06c5c
|
4
|
+
data.tar.gz: 568caddb9d7f929e9dfba7b6b27b2840c36ad302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cb4f3aa6c7f29d4a2f05f82a961a298943801a528da3915e77d7fd1fc5ab85a514427da879520b1d6e844457b91f6fb7f61017feb43f898d0e0d8648f145f97
|
7
|
+
data.tar.gz: d782d81469c340aa3cd3016b4e83041eaf45f3ff1d14201471a7aec1ab3d696f4ec83490cf82bc75aa0c08e4882b752c20dc2c00fdf55659a4d3f3885e66ecdf
|
data/.gitignore
CHANGED
data/README.markdown
CHANGED
@@ -1,41 +1,26 @@
|
|
1
|
+
[](https://circleci.com/gh/moviepilot/minimum-term/tree/master) [](https://coveralls.io/github/moviepilot/minimum-term?branch=master) [](https://codeclimate.com/github/moviepilot/minimum-term)
|
1
2
|
# Minimum term
|
2
3
|
|
3
|
-
This
|
4
|
+
This gem can:
|
4
5
|
|
6
|
+
- convert MSON to JSON Schema files
|
7
|
+
- read a directory which contains one directory per service
|
8
|
+
- read a publish.mson and a consume.mson from each service
|
9
|
+
- build a model of your infrastructure knowing
|
10
|
+
- which services publishes what to which other service
|
11
|
+
- which service consumes what from which other service
|
12
|
+
- if all services consume and publish conforming to their contracts.
|
5
13
|
|
6
|
-
|
14
|
+
You likely don't want to use it on its own but head on over to the [Old Maid](https://github.com/moviepilot/old-maid) gem which explains things in more detail. If you're just looking for ONE way to transform MSON files into JSON Schema, read on:
|
7
15
|
|
8
|
-
|
9
|
-
https://raw.github.com/apiaryio/drafter/master/tools/homebrew/drafter.rb`
|
10
|
-
- run `bundle`
|
11
|
-
|
12
|
-
## Tests and development
|
13
|
-
- run `guard` in a spare terminal which will run the tests,
|
14
|
-
install gems, and so forth
|
15
|
-
- run `rspec spec` to run all the tests
|
16
|
-
- check out `open coverage/index.html` or `open coverage/rcov/index.html`
|
17
|
-
- run `bundle console` to play around with a console
|
18
|
-
|
19
|
-
## Structure
|
20
|
-
- Infrastructure
|
21
|
-
- Service
|
22
|
-
- Contracts
|
23
|
-
- Publish contract
|
24
|
-
- PublishedObjects
|
25
|
-
- Consume contract
|
26
|
-
- ConsumedObjects
|
27
|
-
|
28
|
-
|
29
|
-
## Convert MSON to JSON Schema files
|
16
|
+
## Getting started
|
30
17
|
First, check out [this API Blueprint map](https://github.com/apiaryio/api-blueprint/wiki/API-Blueprint-Map) to understand how _API Blueprint_ documents are laid out:
|
31
18
|
|
32
19
|

|
33
20
|
|
34
21
|
You can see that their structure covers a full API use case with resource groups, single resources, actions on those resources including requests and responses. All we want, though, is the little red top level branch called `Data structures`.
|
35
22
|
|
36
|
-
|
37
|
-
|
38
|
-
So for now, we use a command line tool called [drafter](https://github.com/apiaryio/drafter) to convert MSON into an _API Blueprint_ AST. From that AST we pic the `Data structures` entry and convert it into [JSON Schema]()s
|
23
|
+
We're using a ruby gem called [RedSnow](https://github.com/apiaryio/redsnow), which has bindings to [SnowCrash](https://github.com/apiaryio/snowcrash) which parses _API Blueprints_ into an AST.
|
39
24
|
|
40
25
|
Luckily, a rake task does all that for you. To convert all `*.mson` files in `contracts/` into `*.schema.json` files,
|
41
26
|
|
@@ -56,3 +41,23 @@ OK /home/dev/minimum-term/contracts/missing_required/consume.mson
|
|
56
41
|
OK /home/dev/minimum-term/contracts/publisher/publish.mson
|
57
42
|
/home/dev/minimum-term$
|
58
43
|
```
|
44
|
+
|
45
|
+
## Tests and development
|
46
|
+
- run `bundle` once
|
47
|
+
- run `guard` in a spare terminal which will run the tests,
|
48
|
+
install gems, and so forth
|
49
|
+
- run `rspec spec` to run all the tests
|
50
|
+
- check out `open coverage/index.html` or `open coverage/rcov/index.html`
|
51
|
+
- run `bundle console` to play around with a console
|
52
|
+
|
53
|
+
## Structure
|
54
|
+
|
55
|
+
By converting all files in a directory this gem will build up the following relationships:
|
56
|
+
|
57
|
+
- Infrastructure
|
58
|
+
- Service
|
59
|
+
- Contracts
|
60
|
+
- Publish contract
|
61
|
+
- PublishedObjects
|
62
|
+
- Consume contract
|
63
|
+
- ConsumedObjects
|
data/circle.yml
CHANGED
@@ -2,6 +2,7 @@ require 'fileutils'
|
|
2
2
|
require 'open3'
|
3
3
|
require 'minimum-term/conversion/apiary_to_json_schema'
|
4
4
|
require 'minimum-term/conversion/error'
|
5
|
+
require 'redsnow'
|
5
6
|
|
6
7
|
module MinimumTerm
|
7
8
|
module Conversion
|
@@ -23,11 +24,10 @@ module MinimumTerm
|
|
23
24
|
|
24
25
|
# Parse MSON to an apiary blueprint AST
|
25
26
|
# (see https://github.com/apiaryio/api-blueprint/wiki/API-Blueprint-Map)
|
26
|
-
|
27
|
-
raise Error, "Error: #{to_ast}" unless to_ast[:status] == 0
|
27
|
+
ast_file = mson_to_ast_json(filename)
|
28
28
|
|
29
29
|
# Pluck out Data structures from it
|
30
|
-
data_structures = data_structures_from_blueprint_ast(
|
30
|
+
data_structures = data_structures_from_blueprint_ast(ast_file)
|
31
31
|
|
32
32
|
# Generate json schema from each contained data structure
|
33
33
|
schema = {
|
@@ -83,9 +83,8 @@ module MinimumTerm
|
|
83
83
|
# }
|
84
84
|
#
|
85
85
|
data_structures.each do |data|
|
86
|
-
|
87
|
-
id
|
88
|
-
json= DataStructure.new(id, schema_data, data_structure_autoscope).to_json
|
86
|
+
id = data['name']['literal']
|
87
|
+
json= DataStructure.new(id, data, data_structure_autoscope).to_json
|
89
88
|
member = json.delete('title')
|
90
89
|
schema['definitions'][member] = json
|
91
90
|
schema['properties'][member] = {"$ref" => "#/definitions/#{member}"}
|
@@ -96,12 +95,12 @@ module MinimumTerm
|
|
96
95
|
File.open(outfile, 'w'){ |f| f.puts JSON.pretty_generate(schema) }
|
97
96
|
|
98
97
|
# Clean up
|
99
|
-
FileUtils.rm_f(
|
98
|
+
FileUtils.rm_f(ast_file) unless keep_intermediary_files
|
100
99
|
true
|
101
100
|
end
|
102
101
|
|
103
102
|
def self.data_structures_from_blueprint_ast(filename)
|
104
|
-
c = JSON.parse(open(filename).read)['content'].first
|
103
|
+
c = JSON.parse(open(filename).read)['ast']['content'].first
|
105
104
|
return [] unless c
|
106
105
|
c['content']
|
107
106
|
end
|
@@ -110,16 +109,24 @@ module MinimumTerm
|
|
110
109
|
input = filename
|
111
110
|
output = filename.gsub(/\.\w+$/, '.blueprint-ast.json')
|
112
111
|
|
113
|
-
cmd = "drafter -u -f json -o #{Shellwords.escape(output)} #{Shellwords.escape(input)}"
|
114
|
-
stdin, stdout, status = Open3.capture3(cmd)
|
115
112
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
113
|
+
parse_result = FFI::MemoryPointer.new :pointer
|
114
|
+
RedSnow::Binding.drafter_c_parse(open(input).read, 0, parse_result)
|
115
|
+
parse_result = parse_result.get_pointer(0)
|
116
|
+
|
117
|
+
status = -1
|
118
|
+
result = ''
|
119
|
+
|
120
|
+
unless parse_result.null?
|
121
|
+
status = 0
|
122
|
+
result = parse_result.read_string
|
123
|
+
end
|
124
|
+
|
125
|
+
File.open(output, 'w'){ |f| f.puts(result) }
|
126
|
+
|
127
|
+
output
|
128
|
+
ensure
|
129
|
+
RedSnow::Memory.free(parse_result)
|
123
130
|
end
|
124
131
|
end
|
125
132
|
end
|
@@ -26,47 +26,46 @@ module MinimumTerm
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def add_description_to_json_schema
|
29
|
-
return unless @data['
|
30
|
-
description = @data['
|
29
|
+
return unless @data['sections']
|
30
|
+
description = @data['sections'].select{|d| d['class'] == 'blockDescription' }.first
|
31
31
|
return unless description
|
32
|
-
@schema['description'] = description.strip
|
32
|
+
@schema['description'] = description['content'].strip
|
33
33
|
end
|
34
34
|
|
35
35
|
def add_properties_to_json_schema
|
36
|
-
return unless @data['
|
37
|
-
members = @data['content'].select{|d| d['
|
36
|
+
return unless @data['sections']
|
37
|
+
members = @data['sections'].select{|d| d['class'] == 'memberType' }.first['content'].select{|d| d['class'] == 'property' }
|
38
38
|
members.each do |s|
|
39
39
|
content = s['content']
|
40
|
-
|
40
|
+
type_definition = content['valueDefinition']['typeDefinition']
|
41
|
+
type = type_definition['typeSpecification']['name']
|
41
42
|
|
42
43
|
spec = {}
|
43
|
-
name =
|
44
|
+
name = content['name']['literal'].underscore
|
44
45
|
|
45
46
|
# This is either type: primimtive or $ref: reference_name
|
46
47
|
spec.merge!(primitive_or_reference(type))
|
47
48
|
|
48
|
-
value_content = content['value']['content']
|
49
|
-
|
50
49
|
# We might have a description
|
51
|
-
spec['description'] = s['
|
50
|
+
spec['description'] = s['description']
|
52
51
|
|
53
52
|
# If it's an array, we need to pluck out the item types
|
54
53
|
if type == 'array'
|
55
|
-
nestedTypes =
|
54
|
+
nestedTypes = type_definition['typeSpecification']['nestedTypes']
|
56
55
|
spec['items'] = nestedTypes.map{|t| primitive_or_reference(t) }
|
57
56
|
|
58
57
|
# If it's an object, we need recursion
|
59
58
|
elsif type == 'object'
|
60
59
|
spec['properties'] = {}
|
61
|
-
|
62
|
-
data_structure = DataStructure.new('tmp', content
|
60
|
+
content['sections'].select{|d| d['class'] == 'memberType'}.each do |data|
|
61
|
+
data_structure = DataStructure.new('tmp', content, @scope).to_json
|
63
62
|
spec['properties'].merge!(data_structure['properties'])
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
67
66
|
@schema['properties'][name] = spec
|
68
|
-
if attributes =
|
69
|
-
@schema['required'] << name if attributes
|
67
|
+
if attributes = type_definition['attributes']
|
68
|
+
@schema['required'] << name if attributes.include?('required')
|
70
69
|
end
|
71
70
|
end
|
72
71
|
end
|
@@ -75,7 +74,7 @@ module MinimumTerm
|
|
75
74
|
if PRIMITIVES.include?(type)
|
76
75
|
{ 'type' => type }
|
77
76
|
else
|
78
|
-
{ '$ref' => "#/definitions/#{self.class.scope(@scope, type)}" }
|
77
|
+
{ '$ref' => "#/definitions/#{self.class.scope(@scope, type['literal'])}" }
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
data/lib/minimum-term/version.rb
CHANGED
data/minimum-term.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency "activesupport", ["~> 4.2"]
|
23
23
|
spec.add_runtime_dependency "rake", ["~> 10.2"]
|
24
24
|
spec.add_runtime_dependency "json-schema", ["~> 2.5"]
|
25
|
+
spec.add_runtime_dependency "redsnow", ["~> 0.4"]
|
25
26
|
spec.add_runtime_dependency "colorize"
|
26
27
|
|
27
28
|
spec.add_development_dependency "bundler", ["~> 1"]
|
@@ -29,5 +30,6 @@ Gem::Specification.new do |spec|
|
|
29
30
|
spec.add_development_dependency "guard-ctags-bundler", ["~> 1.4"]
|
30
31
|
spec.add_development_dependency "guard-rspec", ["~> 4.6"]
|
31
32
|
spec.add_development_dependency "rspec", ["~> 3.3"]
|
32
|
-
spec.add_development_dependency "
|
33
|
+
spec.add_development_dependency "coveralls", ["~> 0.8"]
|
34
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
33
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minimum-term
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jannis Hermanns
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: redsnow
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.4'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: colorize
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,19 +151,33 @@ dependencies:
|
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '3.3'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
154
|
+
name: coveralls
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
157
|
- - "~>"
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: '0.
|
159
|
+
version: '0.8'
|
146
160
|
type: :development
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version: '0.
|
166
|
+
version: '0.8'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: codeclimate-test-reporter
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
153
181
|
description: Specify which objects your services publish or consume in MSON (markdown)
|
154
182
|
and let this gem validate these contracts.
|
155
183
|
email:
|
@@ -218,3 +246,4 @@ signing_key:
|
|
218
246
|
specification_version: 4
|
219
247
|
summary: Markdown publish/consume contract parser and validator
|
220
248
|
test_files: []
|
249
|
+
has_rdoc:
|