eazypi 0.0.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +304 -0
- data/CHANGELOG.md +3 -0
- data/README.md +122 -0
- data/Rakefile +12 -0
- data/lib/eazypi/api.rb +100 -0
- data/lib/eazypi/api_controller.rb +57 -0
- data/lib/eazypi/components.rb +10 -0
- data/lib/eazypi/info.rb +28 -0
- data/lib/eazypi/media_type.rb +16 -0
- data/lib/eazypi/operation.rb +87 -0
- data/lib/eazypi/parameter.rb +37 -0
- data/lib/eazypi/path_item.rb +35 -0
- data/lib/eazypi/request_body.rb +31 -0
- data/lib/eazypi/response.rb +33 -0
- data/lib/eazypi/responses.rb +21 -0
- data/lib/eazypi/schema/array.rb +27 -0
- data/lib/eazypi/schema/object.rb +33 -0
- data/lib/eazypi/schema/primitive.rb +31 -0
- data/lib/eazypi/schema.rb +28 -0
- data/lib/eazypi/serializer.rb +57 -0
- data/lib/eazypi/spec_object.rb +33 -0
- data/lib/eazypi/version.rb +5 -0
- data/lib/eazypi.rb +25 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b60b4097cbd524ad683d3bf4c25158620e491a0638649397da289fc4d63d21e1
|
4
|
+
data.tar.gz: a18fa4781d32592d1dc933d1923dfc389237d04ae02a067420c364cd35c8772c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a96a3e253fea3076ba0953c166b9d31e295160c8c9ab34fbb0e72393ed1bfc647c39d7b9f2e98457c3f7c66b3ddc240cfb27aea0ca0fd25468cb51f41db8e5f7
|
7
|
+
data.tar.gz: '0832c28ce9c3120b63d3d40d3b59e5aea7701dc6b050ffe89c49ce54dbfdb5f74ce05091a0e587c5c2407df95b5a0e4b082cf23441400ce9505f1d6f6692a61a'
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,304 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rake
|
3
|
+
- rubocop-rspec
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 3.0
|
7
|
+
Exclude:
|
8
|
+
- petstore-example/**/*
|
9
|
+
|
10
|
+
Style/StringLiterals:
|
11
|
+
Enabled: true
|
12
|
+
EnforcedStyle: double_quotes
|
13
|
+
|
14
|
+
Style/StringLiteralsInInterpolation:
|
15
|
+
Enabled: true
|
16
|
+
EnforcedStyle: double_quotes
|
17
|
+
|
18
|
+
Layout/LineLength:
|
19
|
+
Max: 120
|
20
|
+
|
21
|
+
Metrics/BlockLength:
|
22
|
+
Exclude:
|
23
|
+
- spec/**/*
|
24
|
+
|
25
|
+
RSpec/FilePath:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
RSpec/ExampleLength:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
RSpec/MultipleExpectations:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
## All new checls
|
35
|
+
|
36
|
+
Gemspec/DeprecatedAttributeAssignment: # new in 1.30
|
37
|
+
Enabled: true
|
38
|
+
Gemspec/DevelopmentDependencies: # new in 1.44
|
39
|
+
Enabled: true
|
40
|
+
Gemspec/RequireMFA: # new in 1.23
|
41
|
+
Enabled: true
|
42
|
+
Layout/LineContinuationLeadingSpace: # new in 1.31
|
43
|
+
Enabled: true
|
44
|
+
Layout/LineContinuationSpacing: # new in 1.31
|
45
|
+
Enabled: true
|
46
|
+
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
47
|
+
Enabled: true
|
48
|
+
Layout/SpaceBeforeBrackets: # new in 1.7
|
49
|
+
Enabled: true
|
50
|
+
Lint/AmbiguousAssignment: # new in 1.7
|
51
|
+
Enabled: true
|
52
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
53
|
+
Enabled: true
|
54
|
+
Lint/AmbiguousRange: # new in 1.19
|
55
|
+
Enabled: true
|
56
|
+
Lint/ConstantOverwrittenInRescue: # new in 1.31
|
57
|
+
Enabled: true
|
58
|
+
Lint/DeprecatedConstants: # new in 1.8
|
59
|
+
Enabled: true
|
60
|
+
Lint/DuplicateBranch: # new in 1.3
|
61
|
+
Enabled: true
|
62
|
+
Lint/DuplicateMagicComment: # new in 1.37
|
63
|
+
Enabled: true
|
64
|
+
Lint/DuplicateMatchPattern: # new in 1.50
|
65
|
+
Enabled: true
|
66
|
+
Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
|
67
|
+
Enabled: true
|
68
|
+
Lint/EmptyBlock: # new in 1.1
|
69
|
+
Enabled: true
|
70
|
+
Lint/EmptyClass: # new in 1.3
|
71
|
+
Enabled: true
|
72
|
+
Lint/EmptyInPattern: # new in 1.16
|
73
|
+
Enabled: true
|
74
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
75
|
+
Enabled: true
|
76
|
+
Lint/ItWithoutArgumentsInBlock: # new in 1.59
|
77
|
+
Enabled: true
|
78
|
+
Lint/LambdaWithoutLiteralBlock: # new in 1.8
|
79
|
+
Enabled: true
|
80
|
+
Lint/LiteralAssignmentInCondition: # new in 1.58
|
81
|
+
Enabled: true
|
82
|
+
Lint/MixedCaseRange: # new in 1.53
|
83
|
+
Enabled: true
|
84
|
+
Lint/NoReturnInBeginEndBlocks: # new in 1.2
|
85
|
+
Enabled: true
|
86
|
+
Lint/NonAtomicFileOperation: # new in 1.31
|
87
|
+
Enabled: true
|
88
|
+
Lint/NumberedParameterAssignment: # new in 1.9
|
89
|
+
Enabled: true
|
90
|
+
Lint/OrAssignmentToConstant: # new in 1.9
|
91
|
+
Enabled: true
|
92
|
+
Lint/RedundantDirGlobSort: # new in 1.8
|
93
|
+
Enabled: true
|
94
|
+
Lint/RedundantRegexpQuantifiers: # new in 1.53
|
95
|
+
Enabled: true
|
96
|
+
Lint/RefinementImportMethods: # new in 1.27
|
97
|
+
Enabled: true
|
98
|
+
Lint/RequireRangeParentheses: # new in 1.32
|
99
|
+
Enabled: true
|
100
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
101
|
+
Enabled: true
|
102
|
+
Lint/SymbolConversion: # new in 1.9
|
103
|
+
Enabled: true
|
104
|
+
Lint/ToEnumArguments: # new in 1.1
|
105
|
+
Enabled: true
|
106
|
+
Lint/TripleQuotes: # new in 1.9
|
107
|
+
Enabled: true
|
108
|
+
Lint/UnexpectedBlockArity: # new in 1.5
|
109
|
+
Enabled: true
|
110
|
+
Lint/UnmodifiedReduceAccumulator: # new in 1.1
|
111
|
+
Enabled: true
|
112
|
+
Lint/UselessRescue: # new in 1.43
|
113
|
+
Enabled: true
|
114
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
115
|
+
Enabled: true
|
116
|
+
Metrics/CollectionLiteralLength: # new in 1.47
|
117
|
+
Enabled: true
|
118
|
+
Naming/BlockForwarding: # new in 1.24
|
119
|
+
Enabled: true
|
120
|
+
Security/CompoundHash: # new in 1.28
|
121
|
+
Enabled: true
|
122
|
+
Security/IoMethods: # new in 1.22
|
123
|
+
Enabled: true
|
124
|
+
Style/ArgumentsForwarding: # new in 1.1
|
125
|
+
Enabled: true
|
126
|
+
Style/ArrayIntersect: # new in 1.40
|
127
|
+
Enabled: true
|
128
|
+
Style/CollectionCompact: # new in 1.2
|
129
|
+
Enabled: true
|
130
|
+
Style/ComparableClamp: # new in 1.44
|
131
|
+
Enabled: true
|
132
|
+
Style/ConcatArrayLiterals: # new in 1.41
|
133
|
+
Enabled: true
|
134
|
+
Style/DataInheritance: # new in 1.49
|
135
|
+
Enabled: true
|
136
|
+
Style/DirEmpty: # new in 1.48
|
137
|
+
Enabled: true
|
138
|
+
Style/DocumentDynamicEvalDefinition: # new in 1.1
|
139
|
+
Enabled: true
|
140
|
+
Style/EmptyHeredoc: # new in 1.32
|
141
|
+
Enabled: true
|
142
|
+
Style/EndlessMethod: # new in 1.8
|
143
|
+
Enabled: true
|
144
|
+
Style/EnvHome: # new in 1.29
|
145
|
+
Enabled: true
|
146
|
+
Style/ExactRegexpMatch: # new in 1.51
|
147
|
+
Enabled: true
|
148
|
+
Style/FetchEnvVar: # new in 1.28
|
149
|
+
Enabled: true
|
150
|
+
Style/FileEmpty: # new in 1.48
|
151
|
+
Enabled: true
|
152
|
+
Style/FileRead: # new in 1.24
|
153
|
+
Enabled: true
|
154
|
+
Style/FileWrite: # new in 1.24
|
155
|
+
Enabled: true
|
156
|
+
Style/HashConversion: # new in 1.10
|
157
|
+
Enabled: true
|
158
|
+
Style/HashExcept: # new in 1.7
|
159
|
+
Enabled: true
|
160
|
+
Style/IfWithBooleanLiteralBranches: # new in 1.9
|
161
|
+
Enabled: true
|
162
|
+
Style/InPatternThen: # new in 1.16
|
163
|
+
Enabled: true
|
164
|
+
Style/MagicCommentFormat: # new in 1.35
|
165
|
+
Enabled: true
|
166
|
+
Style/MapCompactWithConditionalBlock: # new in 1.30
|
167
|
+
Enabled: true
|
168
|
+
Style/MapToHash: # new in 1.24
|
169
|
+
Enabled: true
|
170
|
+
Style/MapToSet: # new in 1.42
|
171
|
+
Enabled: true
|
172
|
+
Style/MinMaxComparison: # new in 1.42
|
173
|
+
Enabled: true
|
174
|
+
Style/MultilineInPatternThen: # new in 1.16
|
175
|
+
Enabled: true
|
176
|
+
Style/NegatedIfElseCondition: # new in 1.2
|
177
|
+
Enabled: true
|
178
|
+
Style/NestedFileDirname: # new in 1.26
|
179
|
+
Enabled: true
|
180
|
+
Style/NilLambda: # new in 1.3
|
181
|
+
Enabled: true
|
182
|
+
Style/NumberedParameters: # new in 1.22
|
183
|
+
Enabled: true
|
184
|
+
Style/NumberedParametersLimit: # new in 1.22
|
185
|
+
Enabled: true
|
186
|
+
Style/ObjectThen: # new in 1.28
|
187
|
+
Enabled: true
|
188
|
+
Style/OpenStructUse: # new in 1.23
|
189
|
+
Enabled: true
|
190
|
+
Style/OperatorMethodCall: # new in 1.37
|
191
|
+
Enabled: true
|
192
|
+
Style/QuotedSymbols: # new in 1.16
|
193
|
+
Enabled: true
|
194
|
+
Style/RedundantArgument: # new in 1.4
|
195
|
+
Enabled: true
|
196
|
+
Style/RedundantArrayConstructor: # new in 1.52
|
197
|
+
Enabled: true
|
198
|
+
Style/RedundantConstantBase: # new in 1.40
|
199
|
+
Enabled: true
|
200
|
+
Style/RedundantCurrentDirectoryInPath: # new in 1.53
|
201
|
+
Enabled: true
|
202
|
+
Style/RedundantDoubleSplatHashBraces: # new in 1.41
|
203
|
+
Enabled: true
|
204
|
+
Style/RedundantEach: # new in 1.38
|
205
|
+
Enabled: true
|
206
|
+
Style/RedundantFilterChain: # new in 1.52
|
207
|
+
Enabled: true
|
208
|
+
Style/RedundantHeredocDelimiterQuotes: # new in 1.45
|
209
|
+
Enabled: true
|
210
|
+
Style/RedundantInitialize: # new in 1.27
|
211
|
+
Enabled: true
|
212
|
+
Style/RedundantLineContinuation: # new in 1.49
|
213
|
+
Enabled: true
|
214
|
+
Style/RedundantRegexpArgument: # new in 1.53
|
215
|
+
Enabled: true
|
216
|
+
Style/RedundantRegexpConstructor: # new in 1.52
|
217
|
+
Enabled: true
|
218
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
219
|
+
Enabled: true
|
220
|
+
Style/RedundantStringEscape: # new in 1.37
|
221
|
+
Enabled: true
|
222
|
+
Style/ReturnNilInPredicateMethodDefinition: # new in 1.53
|
223
|
+
Enabled: true
|
224
|
+
Style/SelectByRegexp: # new in 1.22
|
225
|
+
Enabled: true
|
226
|
+
Style/SingleLineDoEndBlock: # new in 1.57
|
227
|
+
Enabled: true
|
228
|
+
Style/StringChars: # new in 1.12
|
229
|
+
Enabled: true
|
230
|
+
Style/SuperWithArgsParentheses: # new in 1.58
|
231
|
+
Enabled: true
|
232
|
+
Style/SwapValues: # new in 1.1
|
233
|
+
Enabled: true
|
234
|
+
Style/YAMLFileRead: # new in 1.53
|
235
|
+
Enabled: true
|
236
|
+
|
237
|
+
Capybara/MatchStyle: # new in 2.17
|
238
|
+
Enabled: true
|
239
|
+
Capybara/NegationMatcher: # new in 2.14
|
240
|
+
Enabled: true
|
241
|
+
Capybara/SpecificActions: # new in 2.14
|
242
|
+
Enabled: true
|
243
|
+
Capybara/SpecificFinders: # new in 2.13
|
244
|
+
Enabled: true
|
245
|
+
Capybara/SpecificMatcher: # new in 2.12
|
246
|
+
Enabled: true
|
247
|
+
FactoryBot/AssociationStyle: # new in 2.23
|
248
|
+
Enabled: true
|
249
|
+
FactoryBot/ConsistentParenthesesStyle: # new in 2.14
|
250
|
+
Enabled: true
|
251
|
+
FactoryBot/FactoryAssociationWithStrategy: # new in 2.23
|
252
|
+
Enabled: true
|
253
|
+
FactoryBot/FactoryNameStyle: # new in 2.16
|
254
|
+
Enabled: true
|
255
|
+
FactoryBot/IdSequence: # new in <<next>>
|
256
|
+
Enabled: true
|
257
|
+
FactoryBot/RedundantFactoryOption: # new in 2.23
|
258
|
+
Enabled: true
|
259
|
+
FactoryBot/SyntaxMethods: # new in 2.7
|
260
|
+
Enabled: true
|
261
|
+
RSpec/BeEmpty: # new in 2.20
|
262
|
+
Enabled: true
|
263
|
+
RSpec/BeEq: # new in 2.9.0
|
264
|
+
Enabled: true
|
265
|
+
RSpec/BeNil: # new in 2.9.0
|
266
|
+
Enabled: true
|
267
|
+
RSpec/ChangeByZero: # new in 2.11
|
268
|
+
Enabled: true
|
269
|
+
RSpec/ContainExactly: # new in 2.19
|
270
|
+
Enabled: true
|
271
|
+
RSpec/DuplicatedMetadata: # new in 2.16
|
272
|
+
Enabled: true
|
273
|
+
RSpec/ExcessiveDocstringSpacing: # new in 2.5
|
274
|
+
Enabled: true
|
275
|
+
RSpec/IdenticalEqualityAssertion: # new in 2.4
|
276
|
+
Enabled: true
|
277
|
+
RSpec/IndexedLet: # new in 2.20
|
278
|
+
Enabled: true
|
279
|
+
RSpec/MatchArray: # new in 2.19
|
280
|
+
Enabled: true
|
281
|
+
RSpec/NoExpectationExample: # new in 2.13
|
282
|
+
Enabled: true
|
283
|
+
RSpec/PendingWithoutReason: # new in 2.16
|
284
|
+
Enabled: true
|
285
|
+
RSpec/RedundantAround: # new in 2.19
|
286
|
+
Enabled: true
|
287
|
+
RSpec/SkipBlockInsideExample: # new in 2.19
|
288
|
+
Enabled: true
|
289
|
+
RSpec/SortMetadata: # new in 2.14
|
290
|
+
Enabled: true
|
291
|
+
RSpec/SubjectDeclaration: # new in 2.5
|
292
|
+
Enabled: true
|
293
|
+
RSpec/VerifiedDoubleReference: # new in 2.10.0
|
294
|
+
Enabled: true
|
295
|
+
RSpec/Rails/AvoidSetupHook: # new in 2.4
|
296
|
+
Enabled: true
|
297
|
+
RSpec/Rails/HaveHttpStatus: # new in 2.12
|
298
|
+
Enabled: true
|
299
|
+
RSpec/Rails/InferredSpecType: # new in 2.14
|
300
|
+
Enabled: true
|
301
|
+
RSpec/Rails/MinitestAssertions: # new in 2.17
|
302
|
+
Enabled: true
|
303
|
+
RSpec/Rails/TravelAround: # new in 2.19
|
304
|
+
Enabled: true
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# Eazypi
|
2
|
+
|
3
|
+
bundle exec rake release
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
8
|
+
|
9
|
+
$ bundle add eazypi
|
10
|
+
|
11
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
12
|
+
|
13
|
+
$ gem install eazypi
|
14
|
+
|
15
|
+
## TODO
|
16
|
+
|
17
|
+
Currently this is in pre-alpha phase, and lot is left to do.
|
18
|
+
|
19
|
+
* Use components automatically
|
20
|
+
* Enforce input
|
21
|
+
* Fix array for query parameters
|
22
|
+
* Variants of serializers
|
23
|
+
* Enforce output
|
24
|
+
* Examples into schema
|
25
|
+
* Output headers
|
26
|
+
* Security
|
27
|
+
* Tags
|
28
|
+
* Basic conformance
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
### Create an API definition
|
33
|
+
|
34
|
+
Create a new API class and include `Eazypi::Api`. Then use the DSL helper methods to define the API.
|
35
|
+
Per OpenAPI spec it is required to include the info
|
36
|
+
|
37
|
+
~~~
|
38
|
+
class Api::V1::Example
|
39
|
+
include Eazypi::Api
|
40
|
+
|
41
|
+
info do
|
42
|
+
title "Example API"
|
43
|
+
|
44
|
+
version "0.0.1"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
~~~
|
48
|
+
|
49
|
+
### Create a controller Class
|
50
|
+
|
51
|
+
Create a normal rails controller and use the DSL to define operations.
|
52
|
+
|
53
|
+
~~~
|
54
|
+
class Api::V1::ExampleController
|
55
|
+
operation :get, '/examples' do
|
56
|
+
response 200, [String]
|
57
|
+
|
58
|
+
render do
|
59
|
+
render json: { examples: ['A', 'B'] }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
~~~
|
64
|
+
|
65
|
+
Also for every new controller you need to define it in your Api Definition from before
|
66
|
+
|
67
|
+
~~~
|
68
|
+
class Api::V1::Example
|
69
|
+
...
|
70
|
+
|
71
|
+
load_controller_class Api::V1::ExampleController
|
72
|
+
end
|
73
|
+
~~~
|
74
|
+
|
75
|
+
### Mount routes
|
76
|
+
|
77
|
+
In `config/routes` mount your API definition
|
78
|
+
|
79
|
+
~~~
|
80
|
+
Rails.application.routes.draw do
|
81
|
+
scope '/api/v1' do
|
82
|
+
Api::V1::Example.mount(self)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
~~~
|
86
|
+
|
87
|
+
### See openapi file
|
88
|
+
|
89
|
+
Run your rails server
|
90
|
+
Go to `localhost:3000/api/v1/openapi.json` or `localhost:3000/api/v1/openapi.yaml`
|
91
|
+
|
92
|
+
## Goals
|
93
|
+
|
94
|
+
The goal is to create an easy to use DSL to create nice OpenAPI defined API's.
|
95
|
+
|
96
|
+
The idea is that the code & documentation live together, but also that it is not possible to accidently change
|
97
|
+
the API but not update the documentation (especially regarding input & output parameters).
|
98
|
+
|
99
|
+
|
100
|
+
## Limitations
|
101
|
+
|
102
|
+
Feel free to prepare pull requests if you want to improve on these limitations
|
103
|
+
|
104
|
+
* Only application/json supported (not XML)
|
105
|
+
* Only supports OpenAPI 3.0.3
|
106
|
+
|
107
|
+
|
108
|
+
## Out of scope
|
109
|
+
|
110
|
+
* No UI to render the documentation. It is recommended to do this outside your rails application. For development you can use rswag-ui or similar
|
111
|
+
* Not guaranteed to deliver valid/conformant OpenAPI spec. It is recommended to run an OpenAPI validator.
|
112
|
+
We might add errors or warnings for common mistakes, but creating a spec file without errors is not guaranteed.
|
113
|
+
|
114
|
+
## Development
|
115
|
+
|
116
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
117
|
+
|
118
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
119
|
+
|
120
|
+
## Contributing
|
121
|
+
|
122
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/eazypi.
|
data/Rakefile
ADDED
data/lib/eazypi/api.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# Main API endpoint. Include this module to start defining your own API's.
|
5
|
+
module Api
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
# ClassMethods that can be used in your API definition
|
11
|
+
module ClassMethods
|
12
|
+
def info(&block)
|
13
|
+
@info ||= Info.new
|
14
|
+
|
15
|
+
@info.load(&block) if block_given?
|
16
|
+
|
17
|
+
@info
|
18
|
+
end
|
19
|
+
|
20
|
+
def paths
|
21
|
+
@paths ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_controller(controller_klass)
|
25
|
+
controller_klass.operations.each do |operation|
|
26
|
+
paths[operation.path] ||= PathItem.new
|
27
|
+
|
28
|
+
paths[operation.path].send(operation.method, operation)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def components
|
33
|
+
@components ||= Components.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def servers
|
37
|
+
[]
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_openapi_spec
|
41
|
+
{
|
42
|
+
"openapi" => "3.0.3", # Future improvement allow different version
|
43
|
+
"info" => info.to_openapi_spec,
|
44
|
+
"paths" => paths.transform_keys do |path|
|
45
|
+
Operation.normalized_path(path)
|
46
|
+
end.transform_values(&:to_openapi_spec),
|
47
|
+
"servers" => servers.map(&:to_openapi_spec),
|
48
|
+
"components" => components.to_openapi_spec
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def mount(router) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
53
|
+
prepare_controller_class
|
54
|
+
|
55
|
+
router.get "openapi.:format", to: "#{ancestors[0].name.underscore}/eazypi#show"
|
56
|
+
|
57
|
+
paths.each do |path_name, path_item|
|
58
|
+
%i[get post patch put delete].each do |http_method|
|
59
|
+
operation = path_item.send(http_method)
|
60
|
+
next unless operation
|
61
|
+
|
62
|
+
controller_router_name = operation.controller_klass.name[...-"Controller".length]
|
63
|
+
router.send(
|
64
|
+
http_method,
|
65
|
+
path_name,
|
66
|
+
to: "#{controller_router_name.underscore}##{operation.controller_method}"
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def prepare_controller_class
|
75
|
+
ancestors[0].const_set("EazypiController", controller_class)
|
76
|
+
end
|
77
|
+
|
78
|
+
def controller_class # rubocop:todo Metrics/MethodLength
|
79
|
+
@controller_class ||= begin
|
80
|
+
api_instance = self
|
81
|
+
|
82
|
+
klass = Class.new(ActionController::Base)
|
83
|
+
klass.define_method(:show) do
|
84
|
+
puts "HERER AI MA "
|
85
|
+
|
86
|
+
if params[:format] == "json"
|
87
|
+
render json: api_instance.to_openapi_spec
|
88
|
+
elsif params[:format] == "yaml"
|
89
|
+
render plain: api_instance.to_openapi_spec.to_yaml, content_type: "text/yaml"
|
90
|
+
else
|
91
|
+
raise "#{params[:format]} not supported"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
klass
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# Include this module in your Rails controller to define operations
|
5
|
+
module ApiController
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_variable_set(:@operations, [])
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Class methods to be used in your own API controller
|
12
|
+
module ClassMethods
|
13
|
+
def operation(method, path_string, &block)
|
14
|
+
method_name = determine_method_name(method, path_string)
|
15
|
+
|
16
|
+
op = Operation.new(self, method_name, path_string, method)
|
17
|
+
op.load(&block)
|
18
|
+
|
19
|
+
define_method(method_name) do
|
20
|
+
op.call(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
@operations << op
|
24
|
+
|
25
|
+
op
|
26
|
+
end
|
27
|
+
|
28
|
+
def operations
|
29
|
+
@operations
|
30
|
+
end
|
31
|
+
|
32
|
+
def determine_method_name(http_method, _path_string) # rubocop:todo Metrics/MethodLength
|
33
|
+
controller_base_name = case http_method
|
34
|
+
when :get
|
35
|
+
:show
|
36
|
+
when :post
|
37
|
+
:create
|
38
|
+
when :patch, :put
|
39
|
+
:update
|
40
|
+
when :delete
|
41
|
+
:destroy
|
42
|
+
else
|
43
|
+
raise "Could not generate method name"
|
44
|
+
end
|
45
|
+
controller_method_name = controller_base_name
|
46
|
+
|
47
|
+
counter = 1
|
48
|
+
while method_defined?(controller_method_name)
|
49
|
+
controller_method_name = "#{controller_base_name}#{counter}"
|
50
|
+
counter += 1
|
51
|
+
end
|
52
|
+
|
53
|
+
controller_method_name
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/eazypi/info.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec InfoObject
|
5
|
+
class Info
|
6
|
+
include SpecObject
|
7
|
+
|
8
|
+
spec_attribute :title
|
9
|
+
spec_attribute :summary
|
10
|
+
spec_attribute :description
|
11
|
+
spec_attribute :terms_of_service
|
12
|
+
spec_attribute :contact
|
13
|
+
spec_attribute :license
|
14
|
+
spec_attribute :version
|
15
|
+
|
16
|
+
def to_openapi_spec
|
17
|
+
{
|
18
|
+
"title" => title,
|
19
|
+
"summary" => summary,
|
20
|
+
"description" => description,
|
21
|
+
"termsOfService" => terms_of_service,
|
22
|
+
"contact" => contact,
|
23
|
+
"license" => license,
|
24
|
+
"version" => version
|
25
|
+
}.compact
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec OperationObject
|
5
|
+
class Operation
|
6
|
+
include Eazypi::SpecObject
|
7
|
+
|
8
|
+
spec_attribute :summary
|
9
|
+
spec_attribute :description
|
10
|
+
spec_attribute :operation_id
|
11
|
+
spec_attribute :depcrecated
|
12
|
+
|
13
|
+
attr_reader :controller_klass, :controller_method, :path, :method, :parameters
|
14
|
+
|
15
|
+
def initialize(controller_klass, controller_method, path, method, &block)
|
16
|
+
@controller_klass = controller_klass
|
17
|
+
@controller_method = controller_method
|
18
|
+
@path = path
|
19
|
+
@method = method
|
20
|
+
@parameters = []
|
21
|
+
|
22
|
+
super(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def openapi_templated_path
|
26
|
+
self.class.normalized_path(@path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def parameter(name, location: nil, &block)
|
30
|
+
if location.nil?
|
31
|
+
location = path_parameters.include?(name.to_s) ? "path" : "query"
|
32
|
+
end
|
33
|
+
|
34
|
+
@parameters << Parameter.new(name: name, location: location, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def request_body(&block)
|
38
|
+
@request_body ||= RequestBody.new(&block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def response(status_code, &block)
|
42
|
+
@responses ||= Responses.new
|
43
|
+
|
44
|
+
@responses.add_response(status_code, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def render(&block)
|
48
|
+
@renderer = block
|
49
|
+
end
|
50
|
+
|
51
|
+
def call(controller)
|
52
|
+
controller.instance_exec(&@renderer)
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_openapi_spec
|
56
|
+
{
|
57
|
+
"summary" => summary,
|
58
|
+
"description" => description,
|
59
|
+
"operationId" => operation_id,
|
60
|
+
"depcrecated" => depcrecated,
|
61
|
+
"parameters" => @parameters.empty? ? nil : @parameters&.map(&:to_openapi_spec),
|
62
|
+
"requestBody" => @request_body&.to_openapi_spec,
|
63
|
+
"responses" => @responses&.to_openapi_spec
|
64
|
+
}.compact
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.normalized_path(path)
|
68
|
+
normalized_path = path.dup
|
69
|
+
|
70
|
+
path.scan(PATH_REGEX).each do |match|
|
71
|
+
normalized_path.gsub!(match[1..], "{#{match[2..]}}")
|
72
|
+
end
|
73
|
+
|
74
|
+
normalized_path
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
PATH_REGEX = %r{/:[a-zA-Z0-9_-]+}
|
80
|
+
|
81
|
+
def path_parameters
|
82
|
+
@path_parameters ||= path.scan(PATH_REGEX).map do |match|
|
83
|
+
match[2..]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec ParameterObject
|
5
|
+
class Parameter
|
6
|
+
include Eazypi::SpecObject
|
7
|
+
|
8
|
+
spec_attribute :name
|
9
|
+
spec_attribute :location
|
10
|
+
spec_attribute :description
|
11
|
+
spec_attribute :required
|
12
|
+
spec_attribute :depcrecated
|
13
|
+
spec_attribute :allow_empty_value
|
14
|
+
|
15
|
+
spec_attribute :explode
|
16
|
+
spec_attribute :schema
|
17
|
+
|
18
|
+
def initialize(name:, location:, &block)
|
19
|
+
@name = name
|
20
|
+
@location = location
|
21
|
+
|
22
|
+
super(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_openapi_spec
|
26
|
+
{
|
27
|
+
"name" => name.to_s,
|
28
|
+
"in" => location, # using location as in is a ruby keywork
|
29
|
+
"description" => description,
|
30
|
+
"required" => location == "path" ? true : required,
|
31
|
+
"deprecated" => depcrecated,
|
32
|
+
"allowEmptyValue" => allow_empty_value,
|
33
|
+
"schema" => schema ? Schema.from_object(schema).to_openapi_spec : nil
|
34
|
+
}.compact
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec PathItemObject
|
5
|
+
class PathItem
|
6
|
+
include SpecObject
|
7
|
+
|
8
|
+
spec_attribute :summary
|
9
|
+
spec_attribute :description
|
10
|
+
|
11
|
+
spec_attribute :get
|
12
|
+
spec_attribute :put
|
13
|
+
spec_attribute :post
|
14
|
+
spec_attribute :delete
|
15
|
+
spec_attribute :options
|
16
|
+
spec_attribute :head
|
17
|
+
spec_attribute :patch
|
18
|
+
spec_attribute :trace
|
19
|
+
|
20
|
+
def to_openapi_spec # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
21
|
+
{
|
22
|
+
"summary" => summary,
|
23
|
+
"description" => description,
|
24
|
+
"get" => get&.to_openapi_spec,
|
25
|
+
"put" => put&.to_openapi_spec,
|
26
|
+
"post" => post&.to_openapi_spec,
|
27
|
+
"delete" => delete&.to_openapi_spec,
|
28
|
+
"options" => options&.to_openapi_spec,
|
29
|
+
"head" => head&.to_openapi_spec,
|
30
|
+
"patch" => patch&.to_openapi_spec,
|
31
|
+
"trace" => trace&.to_openapi_spec
|
32
|
+
}.compact
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec RequestBodyObject
|
5
|
+
class RequestBody
|
6
|
+
include SpecObject
|
7
|
+
|
8
|
+
spec_attribute :description
|
9
|
+
spec_attribute :required
|
10
|
+
|
11
|
+
def initialize(&block)
|
12
|
+
@content = {}
|
13
|
+
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def content(body_schema, content_type: "application/json")
|
18
|
+
@content[content_type] = MediaType.new do
|
19
|
+
schema Eazypi::Schema.from_object(body_schema)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_openapi_spec
|
24
|
+
{
|
25
|
+
"description" => description,
|
26
|
+
"content" => @content.transform_values(&:to_openapi_spec),
|
27
|
+
"required" => required
|
28
|
+
}.compact
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec ResponseObject
|
5
|
+
class Response
|
6
|
+
include SpecObject
|
7
|
+
|
8
|
+
spec_attribute :description
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@content = {}
|
12
|
+
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def content(schema, content_type = "application/json")
|
17
|
+
media_type = MediaType.new
|
18
|
+
|
19
|
+
media_type.load do
|
20
|
+
schema Schema.from_object(schema)
|
21
|
+
end
|
22
|
+
|
23
|
+
@content[content_type] = media_type
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_openapi_spec
|
27
|
+
{
|
28
|
+
"description" => description,
|
29
|
+
"content" => @content.transform_values(&:to_openapi_spec)
|
30
|
+
}.compact
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# OpenAPI spec ResponsesObject
|
5
|
+
class Responses
|
6
|
+
def initialize
|
7
|
+
@responses = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_response(status_code, &block)
|
11
|
+
response = Response.new
|
12
|
+
response.load(&block)
|
13
|
+
|
14
|
+
@responses[status_code.to_s] = response
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_openapi_spec
|
18
|
+
@responses.transform_values(&:to_openapi_spec)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
module Schema
|
5
|
+
# Array schema for JSON
|
6
|
+
class Array
|
7
|
+
attr_reader :item_schema
|
8
|
+
|
9
|
+
def initialize(item_schema)
|
10
|
+
@item_schema = item_schema
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_openapi_spec
|
14
|
+
{
|
15
|
+
"type" => "array",
|
16
|
+
"items" => item_schema.to_openapi_spec
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
return false unless other.is_a?(Array)
|
22
|
+
|
23
|
+
other.instance_variable_get(:@item_schema) == @item_schema
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
module Schema
|
5
|
+
# Object schema for Json
|
6
|
+
class Object
|
7
|
+
def initialize
|
8
|
+
@properties = {}
|
9
|
+
@required = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def property(name, schema, required: false)
|
13
|
+
@properties[name] = schema
|
14
|
+
@required << name if required
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_openapi_spec
|
18
|
+
{
|
19
|
+
"type" => "object",
|
20
|
+
"required" => @required.empty? ? nil : @required,
|
21
|
+
"properties" => @properties.transform_values(&:to_openapi_spec)
|
22
|
+
}.compact
|
23
|
+
end
|
24
|
+
|
25
|
+
def ==(other)
|
26
|
+
return false unless other.is_a?(Object)
|
27
|
+
|
28
|
+
other.instance_variable_get(:@properties) == @properties &&
|
29
|
+
other.instance_variable_get(:@required) == @required
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
module Schema
|
5
|
+
# Primitive schema definition
|
6
|
+
class Primitive
|
7
|
+
include SpecObject
|
8
|
+
|
9
|
+
attr_reader :type, :format
|
10
|
+
|
11
|
+
def initialize(type: nil, format: nil)
|
12
|
+
@type = type
|
13
|
+
@format = format
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_openapi_spec
|
17
|
+
{
|
18
|
+
"type" => type,
|
19
|
+
"format" => format
|
20
|
+
}.compact
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
return false unless other.is_a?(Primitive)
|
25
|
+
|
26
|
+
type == other.type &&
|
27
|
+
format == other.format
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# JSON schema
|
5
|
+
module Schema
|
6
|
+
def self.from_object(object) # rubocop:todo Metrics/MethodLength
|
7
|
+
if object.is_a?(::Array)
|
8
|
+
raise "Array needs to have one element" if object.length != 1
|
9
|
+
|
10
|
+
Schema::Array.new(Schema.from_object(object[0]))
|
11
|
+
elsif object == String
|
12
|
+
Schema::Primitive.new(type: "string")
|
13
|
+
elsif object == Integer
|
14
|
+
Schema::Primitive.new(type: "integer")
|
15
|
+
elsif object == Float
|
16
|
+
Schema::Primitive.new(type: "number")
|
17
|
+
elsif object.respond_to?(:to_schema)
|
18
|
+
object.to_schema
|
19
|
+
else
|
20
|
+
raise "Can not convert #{object} to a schema"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "eazypi/schema/array"
|
27
|
+
require "eazypi/schema/object"
|
28
|
+
require "eazypi/schema/primitive"
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# A serializer you can use to define your own Object types easily
|
5
|
+
module Serializer
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# Defines an Attribute on a serializer
|
9
|
+
class Attribute
|
10
|
+
attr_reader :name, :type, :required
|
11
|
+
|
12
|
+
def initialize(name, type:, method_name:, required:)
|
13
|
+
@name = name
|
14
|
+
@type = type
|
15
|
+
@method_name = method_name
|
16
|
+
@required = required
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(object)
|
21
|
+
@object = object
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json(*_args)
|
25
|
+
self.class.attributes.to_h do |attribute|
|
26
|
+
[attribute.name, @object.send(attribute.name)]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
included do
|
31
|
+
@attributes = []
|
32
|
+
|
33
|
+
def self.attribute(attribute_name, type:, method_name: nil, required: false)
|
34
|
+
@attributes << Attribute.new(
|
35
|
+
attribute_name,
|
36
|
+
type: type,
|
37
|
+
method_name: method_name,
|
38
|
+
required: required
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.attributes
|
43
|
+
@attributes
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.to_schema
|
47
|
+
schema = Schema::Object.new
|
48
|
+
|
49
|
+
@attributes.each do |attribute|
|
50
|
+
schema.property attribute.name.to_s, Schema.from_object(attribute.type), required: attribute.required
|
51
|
+
end
|
52
|
+
|
53
|
+
schema
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Eazypi
|
4
|
+
# Base module for OpenAPI spec Objects
|
5
|
+
module SpecObject
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(&block)
|
11
|
+
self.load(&block) if block_given?
|
12
|
+
end
|
13
|
+
|
14
|
+
def load(&block)
|
15
|
+
instance_exec(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_openapi_spec
|
19
|
+
raise "Not implemented"
|
20
|
+
end
|
21
|
+
|
22
|
+
# ClassMethods for SpecObject
|
23
|
+
module ClassMethods
|
24
|
+
def spec_attribute(attribute_name)
|
25
|
+
define_method(attribute_name) do |v = nil|
|
26
|
+
instance_variable_set(:"@#{attribute_name}", v) if v
|
27
|
+
|
28
|
+
instance_variable_get(:"@#{attribute_name}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/eazypi.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Main Eazypi module. Check README.md for details how to start
|
4
|
+
module Eazypi
|
5
|
+
end
|
6
|
+
|
7
|
+
require "active_support"
|
8
|
+
require "action_controller"
|
9
|
+
|
10
|
+
require "eazypi/spec_object"
|
11
|
+
|
12
|
+
require "eazypi/api_controller"
|
13
|
+
require "eazypi/api"
|
14
|
+
require "eazypi/components"
|
15
|
+
require "eazypi/info"
|
16
|
+
require "eazypi/media_type"
|
17
|
+
require "eazypi/operation"
|
18
|
+
require "eazypi/parameter"
|
19
|
+
require "eazypi/path_item"
|
20
|
+
require "eazypi/request_body"
|
21
|
+
require "eazypi/response"
|
22
|
+
require "eazypi/responses"
|
23
|
+
require "eazypi/schema"
|
24
|
+
require "eazypi/serializer"
|
25
|
+
require "eazypi/version"
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eazypi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Samson
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-02-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: actionpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '7.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '7.0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- nathan@nathansamson.be
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".rspec"
|
49
|
+
- ".rubocop.yml"
|
50
|
+
- CHANGELOG.md
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/eazypi.rb
|
54
|
+
- lib/eazypi/api.rb
|
55
|
+
- lib/eazypi/api_controller.rb
|
56
|
+
- lib/eazypi/components.rb
|
57
|
+
- lib/eazypi/info.rb
|
58
|
+
- lib/eazypi/media_type.rb
|
59
|
+
- lib/eazypi/operation.rb
|
60
|
+
- lib/eazypi/parameter.rb
|
61
|
+
- lib/eazypi/path_item.rb
|
62
|
+
- lib/eazypi/request_body.rb
|
63
|
+
- lib/eazypi/response.rb
|
64
|
+
- lib/eazypi/responses.rb
|
65
|
+
- lib/eazypi/schema.rb
|
66
|
+
- lib/eazypi/schema/array.rb
|
67
|
+
- lib/eazypi/schema/object.rb
|
68
|
+
- lib/eazypi/schema/primitive.rb
|
69
|
+
- lib/eazypi/serializer.rb
|
70
|
+
- lib/eazypi/spec_object.rb
|
71
|
+
- lib/eazypi/version.rb
|
72
|
+
homepage: https://gitlab.com/nathansamson/eazypi/-/blob/main/README.md
|
73
|
+
licenses: []
|
74
|
+
metadata:
|
75
|
+
homepage_uri: https://gitlab.com/nathansamson/eazypi/-/blob/main/README.md
|
76
|
+
source_code_uri: https://gitlab.com/nathansamson/eazypi
|
77
|
+
changelog_uri: https://gitlab.com/nathansamson/eazypi/-/blob/main/CHANGELOG.md
|
78
|
+
rubygems_mfa_required: 'true'
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 3.0.0
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubygems_version: 3.4.10
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: An opinionated framework to generate OpenAPI API's for Rails
|
98
|
+
test_files: []
|