matter_compiler 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/features/compose.feature +80 -86
- data/lib/matter_compiler/blueprint.rb +174 -146
- data/lib/matter_compiler/composer.rb +5 -0
- data/lib/matter_compiler/version.rb +1 -1
- data/test/action_test.rb +2 -7
- data/test/blueprint_test.rb +2 -2
- data/test/headers_test.rb +11 -8
- data/test/metadata_test.rb +5 -4
- data/test/parameters_test.rb +23 -16
- data/test/payload_test.rb +1 -1
- data/test/resource_test.rb +2 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9153d21f8315633c3bc9d88554c1ce4e78c32787
|
4
|
+
data.tar.gz: ad37793f494ab8a5ed3e0a853d363fedde362f4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b031392eeeba9b4cb9bc0aca86259cf96d48aa7ad1d278c48c507bb7e96fcac9e1cc48631f9ec48c62c883886e6d0ce389fc58a36d048f9e4898ec75000501c2
|
7
|
+
data.tar.gz: 2ebb07a49858b3a01c7f74746c2f41498cdb4c0834a14836fac9302440b00f951d1bd0d33aa3810d264e0cd55dec9d6d904b38c93afb3918675b8baefc71e125
|
data/Gemfile.lock
CHANGED
data/features/compose.feature
CHANGED
@@ -61,11 +61,11 @@
|
|
61
61
|
|
62
62
|
And a file named "ast.yaml" with:
|
63
63
|
"""
|
64
|
-
_version:
|
64
|
+
_version: 2.0
|
65
65
|
metadata:
|
66
|
-
|
67
|
-
|
68
|
-
name: My API
|
66
|
+
- name: "FORMAT"
|
67
|
+
value: "1A"
|
68
|
+
name: "My API"
|
69
69
|
description: "Description of *My API*.\n\n"
|
70
70
|
resourceGroups:
|
71
71
|
- name:
|
@@ -73,78 +73,73 @@
|
|
73
73
|
resources:
|
74
74
|
- name:
|
75
75
|
description:
|
76
|
-
uriTemplate: /
|
76
|
+
uriTemplate: "/"
|
77
77
|
model:
|
78
78
|
parameters:
|
79
|
-
headers:
|
80
79
|
actions:
|
81
80
|
- name:
|
82
81
|
description:
|
83
|
-
method: GET
|
82
|
+
method: "GET"
|
84
83
|
parameters:
|
85
|
-
headers:
|
86
84
|
examples:
|
87
85
|
- name:
|
88
86
|
description:
|
89
87
|
requests:
|
90
88
|
responses:
|
91
|
-
- name: 200
|
89
|
+
- name: "200"
|
92
90
|
description:
|
93
91
|
headers:
|
94
|
-
|
95
|
-
|
92
|
+
- name: "Content-Type"
|
93
|
+
value: "text/plain"
|
96
94
|
body: "Hello World!\n"
|
97
95
|
schema:
|
98
|
-
- name: Red
|
96
|
+
- name: "Red"
|
99
97
|
description: "Description of *Red* Group.\n\n"
|
100
98
|
resources:
|
101
|
-
- name: My Resource
|
99
|
+
- name: "My Resource"
|
102
100
|
description: "Description of *My Resource*\n\n"
|
103
101
|
uriTemplate: "/myresource/{id}"
|
104
102
|
model:
|
105
|
-
name: My Resource
|
103
|
+
name: "My Resource"
|
106
104
|
description:
|
107
105
|
headers:
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
106
|
+
- name: "Content-Type"
|
107
|
+
value: "application/json"
|
108
|
+
- name: "X-Header"
|
109
|
+
value: "1"
|
112
110
|
body: "{ \"message\": \"Hello World\" }\n"
|
113
111
|
schema: "{ \"$schema\": \"http://json-schema.org/draft-03/schema\" }\n"
|
114
112
|
parameters:
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
headers:
|
113
|
+
- name: "id"
|
114
|
+
description: "Parameter `id` description."
|
115
|
+
type: "number"
|
116
|
+
required: false
|
117
|
+
default: "42"
|
118
|
+
example: "1000"
|
119
|
+
values:
|
123
120
|
actions:
|
124
|
-
- name: Retrieve My Resource
|
121
|
+
- name: "Retrieve My Resource"
|
125
122
|
description:
|
126
|
-
method: GET
|
123
|
+
method: "GET"
|
127
124
|
parameters:
|
128
|
-
headers:
|
129
125
|
examples:
|
130
126
|
- name:
|
131
127
|
description:
|
132
128
|
requests:
|
133
129
|
responses:
|
134
|
-
- name: 200
|
130
|
+
- name: "200"
|
135
131
|
description:
|
136
132
|
headers:
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
133
|
+
- name: "Content-Type"
|
134
|
+
value: "application/json"
|
135
|
+
- name: "X-Header"
|
136
|
+
value: "1"
|
141
137
|
body: "{ \"message\": \"Hello World\" }\n"
|
142
138
|
schema: "{ \"$schema\": \"http://json-schema.org/draft-03/schema\" }\n"
|
143
|
-
- name: Create My Resource
|
139
|
+
- name: "Create My Resource"
|
144
140
|
description:
|
145
|
-
method: POST
|
141
|
+
method: "POST"
|
146
142
|
parameters:
|
147
|
-
headers:
|
148
143
|
examples:
|
149
144
|
- name:
|
150
145
|
description:
|
@@ -152,28 +147,28 @@
|
|
152
147
|
- name:
|
153
148
|
description:
|
154
149
|
headers:
|
155
|
-
|
156
|
-
|
150
|
+
- name: "Content-Type"
|
151
|
+
value: "text/plain"
|
157
152
|
body: "Ni Hao!\n"
|
158
153
|
schema:
|
159
154
|
responses:
|
160
|
-
- name: 204
|
155
|
+
- name: "204"
|
161
156
|
description:
|
162
157
|
headers:
|
163
158
|
body:
|
164
159
|
schema:
|
165
|
-
|
166
160
|
"""
|
167
161
|
|
168
162
|
And a file named "ast.json" with:
|
169
163
|
"""
|
170
164
|
{
|
171
|
-
"_version": "
|
172
|
-
"metadata":
|
173
|
-
|
165
|
+
"_version": "2.0",
|
166
|
+
"metadata": [
|
167
|
+
{
|
168
|
+
"name": "FORMAT",
|
174
169
|
"value": "1A"
|
175
170
|
}
|
176
|
-
|
171
|
+
],
|
177
172
|
"name": "My API",
|
178
173
|
"description": "Description of *My API*.\n\n",
|
179
174
|
"resourceGroups": [
|
@@ -186,15 +181,13 @@
|
|
186
181
|
"description": "",
|
187
182
|
"uriTemplate": "/",
|
188
183
|
"model": {},
|
189
|
-
"parameters":
|
190
|
-
"headers": {},
|
184
|
+
"parameters": [],
|
191
185
|
"actions": [
|
192
186
|
{
|
193
187
|
"name": "",
|
194
188
|
"description": "",
|
195
189
|
"method": "GET",
|
196
|
-
"parameters":
|
197
|
-
"headers": {},
|
190
|
+
"parameters": [],
|
198
191
|
"examples": [
|
199
192
|
{
|
200
193
|
"name": "",
|
@@ -204,11 +197,12 @@
|
|
204
197
|
{
|
205
198
|
"name": "200",
|
206
199
|
"description": "",
|
207
|
-
"headers":
|
208
|
-
|
200
|
+
"headers": [
|
201
|
+
{
|
202
|
+
"name": "Content-Type",
|
209
203
|
"value": "text/plain"
|
210
204
|
}
|
211
|
-
|
205
|
+
],
|
212
206
|
"body": "Hello World!\n",
|
213
207
|
"schema": ""
|
214
208
|
}
|
@@ -229,37 +223,38 @@
|
|
229
223
|
"description": "Description of *My Resource*\n\n",
|
230
224
|
"uriTemplate": "/myresource/{id}",
|
231
225
|
"model": {
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
"X-Header": {
|
239
|
-
"value": "1"
|
240
|
-
}
|
226
|
+
"name": "My Resource",
|
227
|
+
"description": "",
|
228
|
+
"headers": [
|
229
|
+
{
|
230
|
+
"name": "Content-Type",
|
231
|
+
"value": "application/json"
|
241
232
|
},
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
233
|
+
{
|
234
|
+
"name": "X-Header",
|
235
|
+
"value": "1"
|
236
|
+
}
|
237
|
+
],
|
238
|
+
"body": "{ \"message\": \"Hello World\" }\n",
|
239
|
+
"schema": "{ \"$schema\": \"http://json-schema.org/draft-03/schema\" }\n"
|
240
|
+
},
|
241
|
+
"parameters": [
|
242
|
+
{
|
243
|
+
"name": "id",
|
244
|
+
"description": "Parameter `id` description.",
|
248
245
|
"type": "number",
|
249
246
|
"required": false,
|
250
247
|
"default": "42",
|
251
248
|
"example": "1000",
|
252
249
|
"values": []
|
253
250
|
}
|
254
|
-
|
255
|
-
"headers": {},
|
251
|
+
],
|
256
252
|
"actions": [
|
257
253
|
{
|
258
254
|
"name": "Retrieve My Resource",
|
259
255
|
"description": "",
|
260
256
|
"method": "GET",
|
261
|
-
"parameters":
|
262
|
-
"headers": {},
|
257
|
+
"parameters": [],
|
263
258
|
"examples": [
|
264
259
|
{
|
265
260
|
"name": "",
|
@@ -269,14 +264,16 @@
|
|
269
264
|
{
|
270
265
|
"name": "200",
|
271
266
|
"description": "",
|
272
|
-
"headers":
|
273
|
-
|
267
|
+
"headers": [
|
268
|
+
{
|
269
|
+
"name": "Content-Type",
|
274
270
|
"value": "application/json"
|
275
271
|
},
|
276
|
-
|
272
|
+
{
|
273
|
+
"name": "X-Header",
|
277
274
|
"value": "1"
|
278
275
|
}
|
279
|
-
|
276
|
+
],
|
280
277
|
"body": "{ \"message\": \"Hello World\" }\n",
|
281
278
|
"schema": "{ \"$schema\": \"http://json-schema.org/draft-03/schema\" }\n"
|
282
279
|
}
|
@@ -288,8 +285,7 @@
|
|
288
285
|
"name": "Create My Resource",
|
289
286
|
"description": "",
|
290
287
|
"method": "POST",
|
291
|
-
"parameters":
|
292
|
-
"headers": {},
|
288
|
+
"parameters": [],
|
293
289
|
"examples": [
|
294
290
|
{
|
295
291
|
"name": "",
|
@@ -298,11 +294,12 @@
|
|
298
294
|
{
|
299
295
|
"name": "",
|
300
296
|
"description": "",
|
301
|
-
"headers":
|
302
|
-
|
297
|
+
"headers": [
|
298
|
+
{
|
299
|
+
"name": "Content-Type",
|
303
300
|
"value": "text/plain"
|
304
301
|
}
|
305
|
-
|
302
|
+
],
|
306
303
|
"body": "Ni Hao!\n",
|
307
304
|
"schema": ""
|
308
305
|
}
|
@@ -311,7 +308,7 @@
|
|
311
308
|
{
|
312
309
|
"name": "204",
|
313
310
|
"description": "",
|
314
|
-
"headers":
|
311
|
+
"headers": [],
|
315
312
|
"body": "",
|
316
313
|
"schema": ""
|
317
314
|
}
|
@@ -325,7 +322,6 @@
|
|
325
322
|
}
|
326
323
|
]
|
327
324
|
}
|
328
|
-
|
329
325
|
"""
|
330
326
|
|
331
327
|
Scenario: Compose blueprint from an YAML stdin input
|
@@ -364,7 +360,7 @@
|
|
364
360
|
Scenario: Explicitly set API Blueprint Format
|
365
361
|
Given a file named "no-format.yaml" with:
|
366
362
|
"""
|
367
|
-
_version:
|
363
|
+
_version: 2.0
|
368
364
|
metadata:
|
369
365
|
name: My API
|
370
366
|
description:
|
@@ -381,7 +377,7 @@
|
|
381
377
|
Scenario: Attempt to compose a resource without URI template
|
382
378
|
Given a file named "no-uri-template.yaml" with:
|
383
379
|
"""
|
384
|
-
_version:
|
380
|
+
_version: 2.0
|
385
381
|
metadata:
|
386
382
|
name: My API
|
387
383
|
description:
|
@@ -409,8 +405,6 @@
|
|
409
405
|
- name: 200
|
410
406
|
description:
|
411
407
|
headers:
|
412
|
-
Content-Type:
|
413
|
-
value: text/plain
|
414
408
|
body: "Hello World!\n"
|
415
409
|
schema:
|
416
410
|
"""
|
@@ -1,40 +1,58 @@
|
|
1
|
+
require 'object.rb'
|
2
|
+
|
3
|
+
# The classes in this module should be 1:1 with the Snow Crash AST
|
4
|
+
# counterparts (https://github.com/apiaryio/snowcrash/blob/master/src/Blueprint.h).
|
1
5
|
module MatterCompiler
|
2
6
|
|
3
|
-
# The classes in this document should be 1:1 with relevant Snow Crash
|
4
|
-
# counterparts (https://github.com/apiaryio/snowcrash/blob/master/src/Blueprint.h)
|
5
|
-
# until Matter Compiler becomes a wrapper for Snow Crash.
|
6
|
-
|
7
|
-
#
|
8
7
|
# Blueprint AST node
|
8
|
+
# Base class for API Blueprint AST nodes in Matter Compiler.
|
9
9
|
#
|
10
|
+
# @abstract
|
10
11
|
class BlueprintNode
|
12
|
+
|
11
13
|
ONE_INDENTATION_LEVEL = " "
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
# Initialize the node
|
16
|
+
#
|
17
|
+
# @param ast [Array, Hash, nil] a hash or array to initialize the node with or nil
|
18
|
+
def initialize(ast = nil)
|
19
|
+
load_ast!(ast) if ast
|
15
20
|
end
|
16
21
|
|
17
|
-
# Load AST
|
18
|
-
|
22
|
+
# Load AST object content into node
|
23
|
+
#
|
24
|
+
# @param ast [Array, Hash] an ast object to load
|
25
|
+
def load_ast!(ast)
|
19
26
|
end
|
20
27
|
|
21
|
-
# Serialize
|
22
|
-
#
|
28
|
+
# Serialize node to a Markdown string buffer
|
29
|
+
#
|
30
|
+
# @param level [Integer, 0] requested indentation level
|
31
|
+
# @return [String, nil] content of the node serialized into Markdown or nil
|
23
32
|
def serialize(level = 0)
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
36
|
+
# Blueprint AST node with name and description associated
|
37
|
+
#
|
38
|
+
# @attr name [String] name of the node
|
39
|
+
# @attr description [String] description of the node
|
27
40
|
#
|
28
|
-
#
|
29
|
-
#
|
41
|
+
# @abstract
|
30
42
|
class NamedBlueprintNode < BlueprintNode
|
31
|
-
|
32
|
-
|
33
|
-
|
43
|
+
|
44
|
+
attr_accessor :name
|
45
|
+
attr_accessor :description
|
46
|
+
|
47
|
+
def load_ast!(ast)
|
48
|
+
@name = ast[:name]
|
49
|
+
@description = ast[:description]
|
34
50
|
end
|
35
51
|
|
36
|
-
# Ensure
|
37
|
-
#
|
52
|
+
# Ensure the input string buffer ends with two newlines.
|
53
|
+
#
|
54
|
+
# @param buffer [String] a buffer to check
|
55
|
+
# If the buffer does not ends with two newlines the newlines are added.
|
38
56
|
def ensure_description_newlines(buffer)
|
39
57
|
return if description.blank?
|
40
58
|
|
@@ -46,27 +64,28 @@ module MatterCompiler
|
|
46
64
|
end
|
47
65
|
end
|
48
66
|
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
67
|
+
# Blueprint AST node for key-value collections
|
68
|
+
#
|
69
|
+
# @abstract
|
70
|
+
# @attr collection [Array<Hash>] array of key value hashes
|
52
71
|
class KeyValueCollection < BlueprintNode
|
72
|
+
|
53
73
|
attr_accessor :collection
|
54
74
|
|
55
|
-
def
|
56
|
-
return if
|
57
|
-
|
75
|
+
def load_ast!(ast)
|
76
|
+
return if ast.empty?
|
58
77
|
@collection = Array.new
|
59
|
-
|
60
|
-
@collection << Hash[
|
78
|
+
ast.each do |item|
|
79
|
+
@collection << Hash[item[:name].to_sym, item[:value]]
|
61
80
|
end
|
62
81
|
end
|
63
82
|
|
64
|
-
# Serialize key value
|
65
|
-
#
|
83
|
+
# Serialize key value collection node to a Markdown string buffer
|
84
|
+
#
|
85
|
+
# @param ignore_keys [Array<String>] array of keys that should be ignored (skipped) during the serialization
|
66
86
|
def serialize(level = 0, ignore_keys = nil)
|
67
87
|
buffer = ""
|
68
88
|
@collection.each do |hash|
|
69
|
-
# Skip ignored keys
|
70
89
|
unless ignore_keys && ignore_keys.include?(hash.keys.first)
|
71
90
|
level.times { buffer << ONE_INDENTATION_LEVEL }
|
72
91
|
buffer << "#{hash.keys.first}: #{hash.values.first}\n"
|
@@ -77,70 +96,73 @@ module MatterCompiler
|
|
77
96
|
buffer
|
78
97
|
end
|
79
98
|
|
80
|
-
#
|
81
|
-
|
99
|
+
# Filter collection keys
|
100
|
+
#
|
101
|
+
# @returns [Array<Hash>] collection without ignored keys
|
102
|
+
def filter_collection(ignore_keys)
|
82
103
|
return @collection if ignore_keys.blank?
|
83
104
|
@collection.select { |kv_item| !ignore_keys.include?(kv_item.keys.first) }
|
84
105
|
end
|
85
106
|
end
|
86
107
|
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
108
|
+
# Metadata collection Blueprint AST node
|
109
|
+
# represents 'metadata section'
|
90
110
|
class Metadata < KeyValueCollection
|
91
111
|
end
|
92
112
|
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
113
|
+
# Headers collection Blueprint AST node
|
114
|
+
# represents 'headers section'
|
96
115
|
class Headers < KeyValueCollection
|
97
116
|
|
117
|
+
# HTTP 'Content-Type' header
|
98
118
|
CONTENT_TYPE_HEADER_KEY = :'Content-Type'
|
99
119
|
|
100
120
|
def serialize(level = 0, ignore_keys = nil)
|
101
|
-
return "" if @collection.blank? ||
|
121
|
+
return "" if @collection.blank? || filter_collection(ignore_keys).blank?
|
102
122
|
|
103
123
|
buffer = ""
|
104
124
|
level.times { buffer << ONE_INDENTATION_LEVEL }
|
105
125
|
buffer << "+ Headers\n\n"
|
106
|
-
|
107
126
|
buffer << super(level + 2, ignore_keys)
|
108
127
|
end
|
109
128
|
|
110
|
-
#
|
129
|
+
# @return [String] the value of 'Content-type' header if present or nil
|
111
130
|
def content_type
|
112
131
|
content_type_header = @collection.detect { |header| header.has_key?(CONTENT_TYPE_HEADER_KEY) }
|
113
132
|
return (content_type_header.nil?) ? nil : content_type_header[CONTENT_TYPE_HEADER_KEY]
|
114
133
|
end
|
115
134
|
end;
|
116
135
|
|
136
|
+
# URI parameter Blueprint AST node
|
137
|
+
# represents one 'parameters section' parameter
|
117
138
|
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
139
|
+
# @attr type [String] an arbitrary type of the parameter or nil
|
140
|
+
# @attr use [Symbol] parameter necessity flag, `:required` or `:optional`
|
141
|
+
# @attr default_value [String] default value of the parameter or nil
|
142
|
+
# This is a value used when the parameter is ommited in the request.
|
143
|
+
# @attr example_value [String] example value of the parameter or nil
|
144
|
+
# @attr values [Array<String>] an enumeration of possible parameter values
|
145
|
+
class Parameter < NamedBlueprintNode
|
146
|
+
|
123
147
|
attr_accessor :type
|
124
148
|
attr_accessor :use
|
125
149
|
attr_accessor :default_value
|
126
150
|
attr_accessor :example_value
|
127
151
|
attr_accessor :values
|
128
152
|
|
129
|
-
def
|
130
|
-
super(
|
131
|
-
@name = name.to_s if name
|
132
|
-
end
|
153
|
+
def load_ast!(ast)
|
154
|
+
super(ast)
|
133
155
|
|
134
|
-
|
135
|
-
@
|
136
|
-
@
|
137
|
-
@
|
138
|
-
@default_value = hash[:default] if hash[:default]
|
139
|
-
@example_value = hash[:example] if hash[:example]
|
156
|
+
@type = ast[:type] if ast[:type]
|
157
|
+
@use = (ast[:required] && ast[:required] == true) ? :required : :optional
|
158
|
+
@default_value = ast[:default] if ast[:default]
|
159
|
+
@example_value = ast[:example] if ast[:example]
|
140
160
|
|
141
|
-
unless
|
161
|
+
unless ast[:values].blank?
|
142
162
|
@values = Array.new
|
143
|
-
|
163
|
+
ast[:values].each do |item|
|
164
|
+
@values << item[:value]
|
165
|
+
end
|
144
166
|
end
|
145
167
|
end
|
146
168
|
|
@@ -209,18 +231,20 @@ module MatterCompiler
|
|
209
231
|
end
|
210
232
|
end
|
211
233
|
|
234
|
+
# Collection of URI parameters Blueprint AST node
|
235
|
+
# represents 'parameters section'
|
212
236
|
#
|
213
|
-
#
|
214
|
-
#
|
237
|
+
# @attr collection [Array<Parameter>] an array of URI parameters
|
215
238
|
class Parameters < BlueprintNode
|
239
|
+
|
216
240
|
attr_accessor :collection
|
217
241
|
|
218
|
-
def
|
219
|
-
return if
|
242
|
+
def load_ast!(ast)
|
243
|
+
return if ast.empty?
|
220
244
|
|
221
245
|
@collection = Array.new
|
222
|
-
|
223
|
-
@collection << Parameter.new(
|
246
|
+
ast.each do |item|
|
247
|
+
@collection << Parameter.new(item)
|
224
248
|
end
|
225
249
|
end
|
226
250
|
|
@@ -237,23 +261,27 @@ module MatterCompiler
|
|
237
261
|
end
|
238
262
|
end
|
239
263
|
|
264
|
+
# HTTP message payload Blueprint AST node
|
265
|
+
# base class for 'payload sections'
|
240
266
|
#
|
241
|
-
#
|
242
|
-
#
|
267
|
+
# @abstract
|
268
|
+
# @attr parameters [Array] ignored
|
269
|
+
# @attr headers [Array<Headers>] array of HTTP header fields of the message or nil
|
270
|
+
# @attr body [String] HTTP-message body or nil
|
271
|
+
# @attr schema [String] HTTP-message body validation schema or nil
|
243
272
|
class Payload < NamedBlueprintNode
|
244
|
-
|
245
|
-
attr_accessor :description
|
273
|
+
|
246
274
|
attr_accessor :parameters
|
247
275
|
attr_accessor :headers
|
248
276
|
attr_accessor :body
|
249
277
|
attr_accessor :schema
|
250
278
|
|
251
|
-
def
|
252
|
-
super(
|
279
|
+
def load_ast!(ast)
|
280
|
+
super(ast)
|
253
281
|
|
254
|
-
@headers = Headers.new(
|
255
|
-
@body =
|
256
|
-
@schema =
|
282
|
+
@headers = Headers.new(ast[:headers]) unless ast[:headers].blank?
|
283
|
+
@body = ast[:body] unless ast[:body].blank?
|
284
|
+
@schema = ast[:schema] unless ast[:schema].blank?
|
257
285
|
end
|
258
286
|
|
259
287
|
def serialize
|
@@ -271,7 +299,7 @@ module MatterCompiler
|
|
271
299
|
end
|
272
300
|
|
273
301
|
unless @body.blank?
|
274
|
-
abbreviated_synax = (headers.blank? || headers.
|
302
|
+
abbreviated_synax = (headers.blank? || headers.filter_collection([Headers::CONTENT_TYPE_HEADER_KEY]).blank?) \
|
275
303
|
& description.blank? \
|
276
304
|
& schema.blank?
|
277
305
|
asset_indent_level = 2
|
@@ -311,10 +339,12 @@ module MatterCompiler
|
|
311
339
|
buffer
|
312
340
|
end
|
313
341
|
|
314
|
-
# Serialize
|
315
|
-
#
|
316
|
-
#
|
317
|
-
|
342
|
+
# Serialize payaload's definition (lead-in)
|
343
|
+
#
|
344
|
+
# @param section [String] section type keyword
|
345
|
+
# @param ignore_name [Boolean] object to ignore section name in serialization, false otherwise
|
346
|
+
# @return [String] buffer with serialized section definition
|
347
|
+
def serialize_definition(section, ignore_name = false)
|
318
348
|
buffer = ""
|
319
349
|
buffer << "+ #{section}"
|
320
350
|
buffer << " #{@name}" unless ignore_name || @name.blank?
|
@@ -327,56 +357,53 @@ module MatterCompiler
|
|
327
357
|
end
|
328
358
|
end
|
329
359
|
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
360
|
+
# Model Payload Blueprint AST node
|
361
|
+
# represents 'model section'
|
333
362
|
class Model < Payload
|
334
363
|
def serialize
|
335
|
-
buffer =
|
364
|
+
buffer = serialize_definition("Model", true)
|
336
365
|
buffer << super
|
337
366
|
end
|
338
367
|
end
|
339
368
|
|
340
|
-
#
|
341
|
-
#
|
342
|
-
#
|
369
|
+
# Request Payload Blueprint AST node
|
370
|
+
# represents 'request section'
|
343
371
|
class Request < Payload
|
344
372
|
def serialize
|
345
|
-
buffer =
|
373
|
+
buffer = serialize_definition("Request")
|
346
374
|
buffer << super
|
347
375
|
end
|
348
376
|
end
|
349
377
|
|
350
|
-
#
|
351
378
|
# Response Payload
|
352
|
-
#
|
379
|
+
# represents 'response section'
|
353
380
|
class Response < Payload;
|
354
381
|
def serialize
|
355
|
-
buffer =
|
382
|
+
buffer = serialize_definition("Response")
|
356
383
|
buffer << super
|
357
384
|
end
|
358
385
|
end
|
359
386
|
|
387
|
+
# Transaction example Blueprint AST node
|
360
388
|
#
|
361
|
-
#
|
362
|
-
#
|
389
|
+
# @attr requests [Array<Request>] example request payloads
|
390
|
+
# @attr response [Array<Response>] example response payloads
|
363
391
|
class TransactionExample < NamedBlueprintNode
|
364
|
-
|
365
|
-
attr_accessor :description
|
392
|
+
|
366
393
|
attr_accessor :requests
|
367
394
|
attr_accessor :responses
|
368
395
|
|
369
|
-
def
|
370
|
-
super(
|
396
|
+
def load_ast!(ast)
|
397
|
+
super(ast)
|
371
398
|
|
372
|
-
unless
|
399
|
+
unless ast[:requests].blank?
|
373
400
|
@requests = Array.new
|
374
|
-
|
401
|
+
ast[:requests].each { |request_ast| @requests << Request.new(request_ast) }
|
375
402
|
end
|
376
403
|
|
377
|
-
unless
|
404
|
+
unless ast[:responses].blank?
|
378
405
|
@responses = Array.new
|
379
|
-
|
406
|
+
ast[:responses].each { |response_ast| @responses << Response.new(response_ast) }
|
380
407
|
end
|
381
408
|
end
|
382
409
|
|
@@ -388,27 +415,27 @@ module MatterCompiler
|
|
388
415
|
end
|
389
416
|
end
|
390
417
|
|
418
|
+
# Action Blueprint AST node
|
419
|
+
# represetns 'action sction'
|
391
420
|
#
|
392
|
-
#
|
393
|
-
#
|
421
|
+
# @attr method [String] HTTP request method or nil
|
422
|
+
# @attr parameters [Parameters] action-specific URI parameters or nil
|
423
|
+
# @attr examples [Array<TransactionExample>] action transaction examples
|
394
424
|
class Action < NamedBlueprintNode
|
425
|
+
|
395
426
|
attr_accessor :method
|
396
|
-
attr_accessor :name
|
397
|
-
attr_accessor :description
|
398
427
|
attr_accessor :parameters
|
399
|
-
attr_accessor :headers
|
400
428
|
attr_accessor :examples
|
401
429
|
|
402
|
-
def
|
403
|
-
super(
|
430
|
+
def load_ast!(ast)
|
431
|
+
super(ast)
|
404
432
|
|
405
|
-
@method =
|
406
|
-
@parameters = Parameters.new(
|
407
|
-
@headers = Headers.new(hash[:headers]) unless hash[:headers].blank?
|
433
|
+
@method = ast[:method]
|
434
|
+
@parameters = Parameters.new(ast[:parameters]) unless ast[:parameters].blank?
|
408
435
|
|
409
|
-
unless
|
436
|
+
unless ast[:examples].blank?
|
410
437
|
@examples = Array.new
|
411
|
-
|
438
|
+
ast[:examples].each { |example_ast| @examples << TransactionExample.new(example_ast) }
|
412
439
|
end
|
413
440
|
end
|
414
441
|
|
@@ -424,42 +451,42 @@ module MatterCompiler
|
|
424
451
|
ensure_description_newlines(buffer)
|
425
452
|
|
426
453
|
buffer << @parameters.serialize unless @parameters.nil?
|
427
|
-
buffer << @headers.serialize unless @headers.nil?
|
428
454
|
|
429
455
|
@examples.each { |example| buffer << example.serialize } unless @examples.nil?
|
430
456
|
buffer
|
431
457
|
end
|
432
458
|
end
|
433
459
|
|
460
|
+
# Resource Blueprint AST node
|
461
|
+
# represents 'resource section'
|
434
462
|
#
|
435
|
-
#
|
436
|
-
#
|
463
|
+
# @attr uri_template [String] RFC 6570 URI template
|
464
|
+
# @attr model [Model] model payload for the resource or nil
|
465
|
+
# @attr parameters [Parameters] action-specific URI parameters or nil
|
466
|
+
# @attr actions [Array<Action>] array of resource actions or nil
|
437
467
|
class Resource < NamedBlueprintNode
|
468
|
+
|
438
469
|
attr_accessor :uri_template
|
439
|
-
attr_accessor :name
|
440
|
-
attr_accessor :description
|
441
470
|
attr_accessor :model
|
442
471
|
attr_accessor :parameters
|
443
|
-
attr_accessor :headers
|
444
472
|
attr_accessor :actions
|
445
473
|
|
446
|
-
def
|
447
|
-
super(
|
474
|
+
def load_ast!(ast)
|
475
|
+
super(ast)
|
448
476
|
|
449
|
-
if
|
477
|
+
if ast[:uriTemplate].blank? || ast[:uriTemplate][0] != '/'
|
450
478
|
failure_message = "Invalid input: A resource is missing URI template"
|
451
|
-
failure_message << " ('#{
|
479
|
+
failure_message << " ('#{ast[:name]}' resource)" unless ast[:name].blank?
|
452
480
|
abort(failure_message);
|
453
481
|
end
|
454
482
|
|
455
|
-
@uri_template =
|
456
|
-
@model = Model.new(
|
457
|
-
@parameters = Parameters.new(
|
458
|
-
@headers = Headers.new(hash[:headers]) unless hash[:headers].blank?
|
483
|
+
@uri_template = ast[:uriTemplate]
|
484
|
+
@model = Model.new(ast[:model]) unless ast[:model].blank?
|
485
|
+
@parameters = Parameters.new(ast[:parameters]) unless ast[:parameters].blank?
|
459
486
|
|
460
|
-
unless
|
487
|
+
unless ast[:actions].blank?
|
461
488
|
@actions = Array.new
|
462
|
-
|
489
|
+
ast[:actions].each { |action_ast| @actions << Action.new(action_ast) }
|
463
490
|
end
|
464
491
|
end
|
465
492
|
|
@@ -476,27 +503,26 @@ module MatterCompiler
|
|
476
503
|
|
477
504
|
buffer << @model.serialize unless @model.nil?
|
478
505
|
buffer << @parameters.serialize unless @parameters.nil?
|
479
|
-
buffer << @headers.serialize unless @headers.nil?
|
480
506
|
|
481
507
|
@actions.each { |action| buffer << action.serialize } unless @actions.nil?
|
482
508
|
buffer
|
483
509
|
end
|
484
510
|
end
|
485
511
|
|
512
|
+
# Resource group Blueprint AST node
|
513
|
+
# represents 'resource group section'
|
486
514
|
#
|
487
|
-
# Resource
|
488
|
-
#
|
515
|
+
# @attr resources [Array<Resource>] array of resources in the group
|
489
516
|
class ResourceGroup < NamedBlueprintNode
|
490
|
-
|
491
|
-
attr_accessor :description
|
517
|
+
|
492
518
|
attr_accessor :resources
|
493
519
|
|
494
|
-
def
|
495
|
-
super(
|
520
|
+
def load_ast!(ast)
|
521
|
+
super(ast)
|
496
522
|
|
497
|
-
unless
|
523
|
+
unless ast[:resources].blank?
|
498
524
|
@resources = Array.new
|
499
|
-
|
525
|
+
ast[:resources].each { |resource_ast| @resources << Resource.new(resource_ast) }
|
500
526
|
end
|
501
527
|
end
|
502
528
|
|
@@ -511,30 +537,32 @@ module MatterCompiler
|
|
511
537
|
end
|
512
538
|
end
|
513
539
|
|
540
|
+
|
541
|
+
# Top-level Blueprint AST node
|
542
|
+
# represents 'blueprint section'
|
514
543
|
#
|
515
|
-
#
|
516
|
-
#
|
544
|
+
# @attr metadata [Metadata] tool-specific metadata collection or nil
|
545
|
+
# @attr resource_groups [Array<ResourceGroup>] array of blueprint resource groups
|
517
546
|
class Blueprint < NamedBlueprintNode
|
547
|
+
|
518
548
|
attr_accessor :metadata
|
519
|
-
attr_accessor :name
|
520
|
-
attr_accessor :description
|
521
549
|
attr_accessor :resource_groups
|
522
550
|
|
523
551
|
VERSION_KEY = :_version
|
524
|
-
SUPPORTED_VERSIONS = ["
|
552
|
+
SUPPORTED_VERSIONS = ["2.0"]
|
525
553
|
|
526
|
-
def
|
527
|
-
super(
|
554
|
+
def load_ast!(ast)
|
555
|
+
super(ast)
|
528
556
|
|
529
557
|
# Load Metadata
|
530
|
-
unless
|
531
|
-
@metadata = Metadata.new(
|
558
|
+
unless ast[:metadata].blank?
|
559
|
+
@metadata = Metadata.new(ast[:metadata])
|
532
560
|
end
|
533
561
|
|
534
562
|
# Load Resource Groups
|
535
|
-
unless
|
563
|
+
unless ast[:resourceGroups].blank?
|
536
564
|
@resource_groups = Array.new
|
537
|
-
|
565
|
+
ast[:resourceGroups].each { |group_ast| @resource_groups << ResourceGroup.new(group_ast) }
|
538
566
|
end
|
539
567
|
end
|
540
568
|
|
@@ -74,6 +74,11 @@ module MatterCompiler
|
|
74
74
|
|
75
75
|
# Check version of the AST
|
76
76
|
unless Blueprint::SUPPORTED_VERSIONS.include?(ast_hash[Blueprint::VERSION_KEY].to_s)
|
77
|
+
|
78
|
+
if ast_hash[Blueprint::VERSION_KEY].to_s == "1.0"
|
79
|
+
puts "Use matter_compiler v0.4.0 to process AST media types prior AST v2.0"
|
80
|
+
end
|
81
|
+
|
77
82
|
abort("Invalid input: Unsupported AST version: '#{ast_hash[Blueprint::VERSION_KEY]}'\n")
|
78
83
|
end
|
79
84
|
|
data/test/action_test.rb
CHANGED
@@ -10,7 +10,6 @@ class ActionTest < Minitest::Test
|
|
10
10
|
:description => "Dolor sit amet\n\n",
|
11
11
|
:method => "GET",
|
12
12
|
:parameters => ParametersTest::AST_HASH,
|
13
|
-
:headers => HeadersTest::AST_HASH,
|
14
13
|
:examples => [TransactionExampleTest::AST_HASH]
|
15
14
|
}
|
16
15
|
|
@@ -18,7 +17,7 @@ class ActionTest < Minitest::Test
|
|
18
17
|
%Q{### Into Action [GET]
|
19
18
|
Dolor sit amet
|
20
19
|
|
21
|
-
#{ParametersTest::BLUEPRINT}#{
|
20
|
+
#{ParametersTest::BLUEPRINT}#{TransactionExampleTest::BLUEPRINT}}
|
22
21
|
|
23
22
|
def test_from_ast_hash
|
24
23
|
action = MatterCompiler::Action.new(ActionTest::AST_HASH)
|
@@ -28,11 +27,7 @@ Dolor sit amet
|
|
28
27
|
|
29
28
|
assert_instance_of MatterCompiler::Parameters, action.parameters
|
30
29
|
assert_instance_of Array, action.parameters.collection
|
31
|
-
assert_equal ParametersTest::AST_HASH.
|
32
|
-
|
33
|
-
assert_instance_of MatterCompiler::Headers, action.headers
|
34
|
-
assert_instance_of Array, action.headers.collection
|
35
|
-
assert_equal HeadersTest::AST_HASH.keys.length, action.headers.collection.length
|
30
|
+
assert_equal ParametersTest::AST_HASH.length, action.parameters.collection.length
|
36
31
|
|
37
32
|
assert_instance_of Array, action.examples
|
38
33
|
assert_equal ActionTest::AST_HASH[:examples].length, action.examples.length
|
data/test/blueprint_test.rb
CHANGED
@@ -30,8 +30,8 @@ Lorem Ipsum
|
|
30
30
|
|
31
31
|
assert_instance_of MatterCompiler::Metadata, blueprint.metadata
|
32
32
|
assert_instance_of Array, blueprint.metadata.collection
|
33
|
-
assert_equal BlueprintTest::AST_HASH[:metadata].
|
34
|
-
assert_equal BlueprintTest::AST_HASH[:metadata]
|
33
|
+
assert_equal BlueprintTest::AST_HASH[:metadata].length, blueprint.metadata.collection.length
|
34
|
+
assert_equal BlueprintTest::AST_HASH[:metadata][0][:name], blueprint.metadata.collection[0].keys[0].to_s
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_serialize
|
data/test/headers_test.rb
CHANGED
@@ -2,20 +2,23 @@ require 'minitest/autorun'
|
|
2
2
|
require 'matter_compiler/blueprint'
|
3
3
|
|
4
4
|
class HeadersTest < Minitest::Test
|
5
|
-
AST_HASH =
|
6
|
-
|
5
|
+
AST_HASH = [
|
6
|
+
{
|
7
|
+
:name => "X-Header",
|
7
8
|
:value => "1"
|
8
9
|
},
|
9
|
-
|
10
|
+
{
|
11
|
+
:name => "Content-Type",
|
10
12
|
:value => "text/plain"
|
11
13
|
}
|
12
|
-
|
14
|
+
]
|
13
15
|
|
14
|
-
AST_HASH_CONTENT_ONLY =
|
15
|
-
|
16
|
+
AST_HASH_CONTENT_ONLY = [
|
17
|
+
{
|
18
|
+
:name => "Content-Type",
|
16
19
|
:value => "text/plain"
|
17
|
-
}
|
18
|
-
|
20
|
+
}
|
21
|
+
]
|
19
22
|
|
20
23
|
BLUEPRINT = \
|
21
24
|
%Q{+ Headers
|
data/test/metadata_test.rb
CHANGED
@@ -2,11 +2,12 @@ require 'minitest/autorun'
|
|
2
2
|
require 'matter_compiler/blueprint'
|
3
3
|
|
4
4
|
class MetadataTest < Minitest::Test
|
5
|
-
AST_HASH =
|
6
|
-
|
7
|
-
:
|
5
|
+
AST_HASH = [
|
6
|
+
{
|
7
|
+
:name => "FORMAT",
|
8
|
+
:value => "1A"
|
8
9
|
}
|
9
|
-
|
10
|
+
]
|
10
11
|
|
11
12
|
BLUEPRINT = \
|
12
13
|
%Q{FORMAT: 1A
|
data/test/parameters_test.rb
CHANGED
@@ -2,19 +2,25 @@ require 'minitest/autorun'
|
|
2
2
|
require 'matter_compiler/blueprint'
|
3
3
|
|
4
4
|
class ParametersTest < Minitest::Test
|
5
|
-
AST_HASH =
|
6
|
-
|
5
|
+
AST_HASH = [
|
6
|
+
{
|
7
|
+
:name => "id",
|
7
8
|
:description => "Lorem\nIpsum\n",
|
8
9
|
:type => "number",
|
9
10
|
:required => false,
|
10
11
|
:default => "42",
|
11
12
|
:example => "1000",
|
12
|
-
:values => [
|
13
|
+
:values => [
|
14
|
+
{ :value => "42" },
|
15
|
+
{ :value => "1000"},
|
16
|
+
{ :value => "1AM4646"}
|
17
|
+
]
|
13
18
|
}
|
14
|
-
|
19
|
+
]
|
15
20
|
|
16
|
-
AST_HASH_MANY =
|
17
|
-
|
21
|
+
AST_HASH_MANY = [
|
22
|
+
{
|
23
|
+
:name => "id",
|
18
24
|
:description => "Lorem",
|
19
25
|
:type => nil,
|
20
26
|
:required => true,
|
@@ -22,7 +28,8 @@ class ParametersTest < Minitest::Test
|
|
22
28
|
:example => nil,
|
23
29
|
:values => nil
|
24
30
|
},
|
25
|
-
|
31
|
+
{
|
32
|
+
:name => "search",
|
26
33
|
:description => "Ipsum",
|
27
34
|
:type => nil,
|
28
35
|
:required => true,
|
@@ -30,7 +37,7 @@ class ParametersTest < Minitest::Test
|
|
30
37
|
:example => nil,
|
31
38
|
:values => nil
|
32
39
|
}
|
33
|
-
|
40
|
+
]
|
34
41
|
|
35
42
|
BLUEPRINT = \
|
36
43
|
%Q{+ Parameters
|
@@ -61,17 +68,17 @@ class ParametersTest < Minitest::Test
|
|
61
68
|
|
62
69
|
parameter = parameters.collection[0]
|
63
70
|
assert_equal :id.to_s, parameter.name
|
64
|
-
assert_equal ParametersTest::AST_HASH[
|
65
|
-
assert_equal ParametersTest::AST_HASH[
|
71
|
+
assert_equal ParametersTest::AST_HASH[0][:description], parameter.description
|
72
|
+
assert_equal ParametersTest::AST_HASH[0][:type], parameter.type
|
66
73
|
assert_equal :optional, parameter.use
|
67
|
-
assert_equal ParametersTest::AST_HASH[
|
68
|
-
assert_equal ParametersTest::AST_HASH[
|
74
|
+
assert_equal ParametersTest::AST_HASH[0][:default], parameter.default_value
|
75
|
+
assert_equal ParametersTest::AST_HASH[0][:example], parameter.example_value
|
69
76
|
|
70
77
|
assert_instance_of Array, parameter.values
|
71
|
-
assert_equal ParametersTest::AST_HASH[
|
72
|
-
assert_equal ParametersTest::AST_HASH[
|
73
|
-
assert_equal ParametersTest::AST_HASH[
|
74
|
-
assert_equal ParametersTest::AST_HASH[
|
78
|
+
assert_equal ParametersTest::AST_HASH[0][:values].length, parameter.values.length
|
79
|
+
assert_equal ParametersTest::AST_HASH[0][:values][0][:value], parameter.values[0]
|
80
|
+
assert_equal ParametersTest::AST_HASH[0][:values][1][:value], parameter.values[1]
|
81
|
+
assert_equal ParametersTest::AST_HASH[0][:values][2][:value], parameter.values[2]
|
75
82
|
end
|
76
83
|
|
77
84
|
def test_serialize
|
data/test/payload_test.rb
CHANGED
@@ -144,7 +144,7 @@ class ResponseTest < Minitest::Test
|
|
144
144
|
|
145
145
|
assert_instance_of MatterCompiler::Headers, response.headers
|
146
146
|
assert_instance_of Array, response.headers.collection
|
147
|
-
assert_equal HeadersTest::AST_HASH.
|
147
|
+
assert_equal HeadersTest::AST_HASH.length, response.headers.collection.length
|
148
148
|
|
149
149
|
assert_equal ResponseTest::AST_HASH[:body], response.body
|
150
150
|
assert_equal ResponseTest::AST_HASH[:schema], response.schema
|
data/test/resource_test.rb
CHANGED
@@ -12,7 +12,6 @@ class ResourceTest < Minitest::Test
|
|
12
12
|
:uriTemplate => "/my-resource/{id}",
|
13
13
|
:model => ModelTest::AST_HASH,
|
14
14
|
:parameters => ParametersTest::AST_HASH,
|
15
|
-
:headers => HeadersTest::AST_HASH,
|
16
15
|
:actions => [ActionTest::AST_HASH]
|
17
16
|
}
|
18
17
|
|
@@ -20,7 +19,7 @@ class ResourceTest < Minitest::Test
|
|
20
19
|
%Q{## My Resource [/my-resource/{id}]
|
21
20
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
22
21
|
|
23
|
-
#{ModelTest::BLUEPRINT}#{ParametersTest::BLUEPRINT}#{
|
22
|
+
#{ModelTest::BLUEPRINT}#{ParametersTest::BLUEPRINT}#{ActionTest::BLUEPRINT}}
|
24
23
|
|
25
24
|
def test_from_ast_hash
|
26
25
|
resource = MatterCompiler::Resource.new(ResourceTest::AST_HASH)
|
@@ -33,11 +32,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
33
32
|
|
34
33
|
assert_instance_of MatterCompiler::Parameters, resource.parameters
|
35
34
|
assert_instance_of Array, resource.parameters.collection
|
36
|
-
assert_equal ParametersTest::AST_HASH.
|
37
|
-
|
38
|
-
assert_instance_of MatterCompiler::Headers, resource.headers
|
39
|
-
assert_instance_of Array, resource.headers.collection
|
40
|
-
assert_equal HeadersTest::AST_HASH.keys.length, resource.headers.collection.length
|
35
|
+
assert_equal ParametersTest::AST_HASH.length, resource.parameters.collection.length
|
41
36
|
|
42
37
|
assert_instance_of Array, resource.actions
|
43
38
|
assert_equal ResourceTest::AST_HASH[:actions].length, resource.actions.length
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: matter_compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zdenek Nemec
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|