apigen 0.0.6 → 0.0.7
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/lib/apigen/formats/json_base.rb +109 -0
- data/lib/apigen/formats/jsonschema.rb +11 -59
- data/lib/apigen/formats/openapi.rb +10 -64
- data/lib/apigen/formats/swagger.rb +10 -60
- data/lib/apigen/migration.rb +55 -0
- data/lib/apigen/model.rb +1 -234
- data/lib/apigen/models/array_type.rb +34 -0
- data/lib/apigen/models/enum_type.rb +25 -0
- data/lib/apigen/models/model.rb +78 -0
- data/lib/apigen/models/object_property.rb +39 -0
- data/lib/apigen/models/object_type.rb +77 -0
- data/lib/apigen/models/oneof_type.rb +33 -0
- data/lib/apigen/models/primary_type.rb +33 -0
- data/lib/apigen/models/reference_type.rb +27 -0
- data/lib/apigen/models/registry.rb +39 -0
- data/lib/apigen/rest.rb +1 -269
- data/lib/apigen/rest/api.rb +73 -0
- data/lib/apigen/rest/endpoint.rb +160 -0
- data/lib/apigen/rest/input.rb +39 -0
- data/lib/apigen/rest/output.rb +45 -0
- metadata +16 -1
@@ -0,0 +1,160 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './input'
|
4
|
+
require_relative './output'
|
5
|
+
|
6
|
+
module Apigen
|
7
|
+
module Rest
|
8
|
+
##
|
9
|
+
# Endpoint is a definition of a specific endpoint in the API, e.g. /users with GET method.
|
10
|
+
class Endpoint
|
11
|
+
PATH_PARAMETER_REGEX = /\{(\w+)\}/
|
12
|
+
|
13
|
+
attribute_setter_getter :name
|
14
|
+
attribute_setter_getter :description
|
15
|
+
attr_reader :outputs
|
16
|
+
attr_reader :path_parameters
|
17
|
+
attr_reader :query_parameters
|
18
|
+
|
19
|
+
def initialize(name)
|
20
|
+
@name = name
|
21
|
+
@method = nil
|
22
|
+
@path = nil
|
23
|
+
@path_parameters = Apigen::ObjectType.new
|
24
|
+
@query_parameters = Apigen::ObjectType.new
|
25
|
+
@input = nil
|
26
|
+
@outputs = []
|
27
|
+
@description = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Declares the HTTP method.
|
32
|
+
def method(method = nil)
|
33
|
+
return @method unless method
|
34
|
+
case method
|
35
|
+
when :get, :post, :put, :delete
|
36
|
+
@method = method
|
37
|
+
else
|
38
|
+
raise "Unknown HTTP method :#{method}."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Declares the endpoint path relative to the host.
|
44
|
+
def path(path = nil, &block)
|
45
|
+
return @path unless path
|
46
|
+
@path = path
|
47
|
+
if PATH_PARAMETER_REGEX.match path
|
48
|
+
set_path_parameters(path, &block)
|
49
|
+
elsif block_given?
|
50
|
+
raise 'A path block was provided but no URL parameter was found.'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Declares query parameters.
|
56
|
+
def query(&block)
|
57
|
+
raise 'You must pass a block when calling `query`.' unless block_given?
|
58
|
+
@query_parameters.instance_eval(&block)
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Declares the input type of an endpoint.
|
63
|
+
def input(&block)
|
64
|
+
return @input unless block_given?
|
65
|
+
@input = Input.new
|
66
|
+
@input.instance_eval(&block)
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Declares the output of an endpoint for a given status code.
|
71
|
+
def output(name, &block)
|
72
|
+
raise "Endpoint :#{@name} declares the output :#{name} twice." if @outputs.find { |o| o.name == name }
|
73
|
+
output = Output.new name
|
74
|
+
@outputs << output
|
75
|
+
raise 'You must pass a block when calling `output`.' unless block_given?
|
76
|
+
output.instance_eval(&block)
|
77
|
+
output
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Updates an already-declared output.
|
82
|
+
def update_output(name, &block)
|
83
|
+
output = @outputs.find { |o| o.name == name }
|
84
|
+
raise "Endpoint :#{@name} never declares the output :#{name} so it cannot be updated." unless output
|
85
|
+
raise 'You must pass a block when calling `update_output`.' unless block_given?
|
86
|
+
output.instance_eval(&block)
|
87
|
+
output
|
88
|
+
end
|
89
|
+
|
90
|
+
def validate(model_registry)
|
91
|
+
validate_properties
|
92
|
+
validate_input(model_registry)
|
93
|
+
validate_path_parameters(model_registry)
|
94
|
+
validate_outputs(model_registry)
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_s
|
98
|
+
repr = "#{@name}:"
|
99
|
+
input_str = @input.to_s
|
100
|
+
repr += " #{input_str}" unless input_str.empty?
|
101
|
+
@outputs.each do |output|
|
102
|
+
repr += "\n-> #{output}"
|
103
|
+
end
|
104
|
+
repr += "\n"
|
105
|
+
repr
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def set_path_parameters(path, &block)
|
111
|
+
block = {} unless block_given?
|
112
|
+
@path_parameters.instance_eval(&block)
|
113
|
+
parameters_found_in_path = path.scan(PATH_PARAMETER_REGEX).map { |parameter, _| parameter.to_sym }
|
114
|
+
ensure_parameters_found_in_path_all_defined(parameters_found_in_path)
|
115
|
+
ensure_defined_parameters_all_appear_in_path(parameters_found_in_path)
|
116
|
+
end
|
117
|
+
|
118
|
+
def ensure_parameters_found_in_path_all_defined(parameters_found_in_path)
|
119
|
+
parameters_found_in_path.each do |parameter|
|
120
|
+
raise "Path parameter :#{parameter} in path #{@path} is not defined." unless @path_parameters.properties.key? parameter
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def ensure_defined_parameters_all_appear_in_path(parameters_found_in_path)
|
125
|
+
@path_parameters.properties.each do |parameter, _type|
|
126
|
+
raise "Parameter :#{parameter} does not appear in path #{@path}." unless parameters_found_in_path.include? parameter
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def validate_properties
|
131
|
+
raise 'One of the endpoints is missing a name.' unless @name
|
132
|
+
raise "Use `method :get/post/put/delete` to set an HTTP method for :#{@name}." unless @method
|
133
|
+
raise "Use `path \"/some/path\"` to assign a path to :#{@name}." unless @path
|
134
|
+
end
|
135
|
+
|
136
|
+
def validate_input(model_registry)
|
137
|
+
case @method
|
138
|
+
when :put, :post
|
139
|
+
raise "Use `input { type :typename }` to assign an input type to :#{@name}." unless @input
|
140
|
+
@input.validate(model_registry)
|
141
|
+
when :get
|
142
|
+
raise "Endpoint :#{@name} with method GET cannot accept an input payload." if @input
|
143
|
+
when :delete
|
144
|
+
raise "Endpoint :#{@name} with method DELETE cannot accept an input payload." if @input
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def validate_path_parameters(model_registry)
|
149
|
+
@path_parameters.validate model_registry
|
150
|
+
end
|
151
|
+
|
152
|
+
def validate_outputs(model_registry)
|
153
|
+
raise "Endpoint :#{@name} does not declare any outputs" if @outputs.empty?
|
154
|
+
@outputs.each do |output|
|
155
|
+
output.validate model_registry
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apigen
|
4
|
+
module Rest
|
5
|
+
##
|
6
|
+
# Input is the request body expected by an API endpoint.
|
7
|
+
class Input
|
8
|
+
attribute_setter_getter :description
|
9
|
+
attribute_setter_getter :example
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@type = nil
|
13
|
+
@description = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Declares the input type.
|
18
|
+
def type(type = nil, &block)
|
19
|
+
return @type unless type
|
20
|
+
@type = Apigen::Model.type type, &block
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate(model_registry)
|
24
|
+
validate_properties
|
25
|
+
model_registry.check_type @type
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
@type.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def validate_properties
|
35
|
+
raise 'Use `type :typename` to assign a type to the input.' unless @type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apigen
|
4
|
+
module Rest
|
5
|
+
##
|
6
|
+
# Output is the response type associated with a specific status code for an API endpoint.
|
7
|
+
class Output
|
8
|
+
attr_reader :name
|
9
|
+
attribute_setter_getter :status
|
10
|
+
attribute_setter_getter :description
|
11
|
+
attribute_setter_getter :example
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
@name = name
|
15
|
+
@status = nil
|
16
|
+
@type = nil
|
17
|
+
@description = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Declares the output type.
|
22
|
+
def type(type = nil, &block)
|
23
|
+
return @type unless type
|
24
|
+
@type = Apigen::Model.type type, &block
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate(model_registry)
|
28
|
+
validate_properties
|
29
|
+
model_registry.check_type @type
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
"#{@name} #{@status} #{@type}"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def validate_properties
|
39
|
+
raise 'One of the outputs is missing a name.' unless @name
|
40
|
+
raise "Use `status [code]` to assign a status code to :#{@name}." unless @status
|
41
|
+
raise "Use `type :typename` to assign a type to :#{@name}." unless @type
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apigen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francois Wouts
|
@@ -16,11 +16,26 @@ executables: []
|
|
16
16
|
extensions: []
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
|
+
- lib/apigen/formats/json_base.rb
|
19
20
|
- lib/apigen/formats/jsonschema.rb
|
20
21
|
- lib/apigen/formats/openapi.rb
|
21
22
|
- lib/apigen/formats/swagger.rb
|
23
|
+
- lib/apigen/migration.rb
|
22
24
|
- lib/apigen/model.rb
|
25
|
+
- lib/apigen/models/array_type.rb
|
26
|
+
- lib/apigen/models/enum_type.rb
|
27
|
+
- lib/apigen/models/model.rb
|
28
|
+
- lib/apigen/models/object_property.rb
|
29
|
+
- lib/apigen/models/object_type.rb
|
30
|
+
- lib/apigen/models/oneof_type.rb
|
31
|
+
- lib/apigen/models/primary_type.rb
|
32
|
+
- lib/apigen/models/reference_type.rb
|
33
|
+
- lib/apigen/models/registry.rb
|
23
34
|
- lib/apigen/rest.rb
|
35
|
+
- lib/apigen/rest/api.rb
|
36
|
+
- lib/apigen/rest/endpoint.rb
|
37
|
+
- lib/apigen/rest/input.rb
|
38
|
+
- lib/apigen/rest/output.rb
|
24
39
|
- lib/apigen/util.rb
|
25
40
|
homepage: https://rubygems.org/gems/apigen
|
26
41
|
licenses:
|