modern 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +8 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +173 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +10 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +36 -0
  10. data/Rakefile +10 -0
  11. data/TODOS.md +4 -0
  12. data/bin/console +9 -0
  13. data/bin/setup +8 -0
  14. data/example/Gemfile +9 -0
  15. data/example/Gemfile.lock +102 -0
  16. data/example/config.ru +11 -0
  17. data/example/example.rb +19 -0
  18. data/lib/modern/app/error_handling.rb +45 -0
  19. data/lib/modern/app/request_handling/input_handling.rb +65 -0
  20. data/lib/modern/app/request_handling/output_handling.rb +54 -0
  21. data/lib/modern/app/request_handling/request_container.rb +55 -0
  22. data/lib/modern/app/request_handling.rb +70 -0
  23. data/lib/modern/app/router.rb +27 -0
  24. data/lib/modern/app/trie_router.rb +37 -0
  25. data/lib/modern/app.rb +82 -0
  26. data/lib/modern/capsule.rb +17 -0
  27. data/lib/modern/configuration.rb +16 -0
  28. data/lib/modern/core_ext/array.rb +23 -0
  29. data/lib/modern/core_ext/hash.rb +17 -0
  30. data/lib/modern/descriptor/content.rb +14 -0
  31. data/lib/modern/descriptor/converters/input/base.rb +29 -0
  32. data/lib/modern/descriptor/converters/input/json.rb +21 -0
  33. data/lib/modern/descriptor/converters/output/base.rb +25 -0
  34. data/lib/modern/descriptor/converters/output/json.rb +48 -0
  35. data/lib/modern/descriptor/converters/output/yaml.rb +21 -0
  36. data/lib/modern/descriptor/converters.rb +4 -0
  37. data/lib/modern/descriptor/core.rb +63 -0
  38. data/lib/modern/descriptor/info.rb +27 -0
  39. data/lib/modern/descriptor/parameters.rb +149 -0
  40. data/lib/modern/descriptor/request_body.rb +13 -0
  41. data/lib/modern/descriptor/response.rb +26 -0
  42. data/lib/modern/descriptor/route.rb +93 -0
  43. data/lib/modern/descriptor/security.rb +104 -0
  44. data/lib/modern/descriptor/server.rb +12 -0
  45. data/lib/modern/descriptor.rb +15 -0
  46. data/lib/modern/doc_generator/open_api3/operations.rb +114 -0
  47. data/lib/modern/doc_generator/open_api3/paths.rb +24 -0
  48. data/lib/modern/doc_generator/open_api3/schema_default_types.rb +50 -0
  49. data/lib/modern/doc_generator/open_api3/schemas.rb +171 -0
  50. data/lib/modern/doc_generator/open_api3/security_schemes.rb +15 -0
  51. data/lib/modern/doc_generator/open_api3.rb +141 -0
  52. data/lib/modern/dsl/info.rb +39 -0
  53. data/lib/modern/dsl/response_builder.rb +41 -0
  54. data/lib/modern/dsl/root.rb +38 -0
  55. data/lib/modern/dsl/route_builder.rb +130 -0
  56. data/lib/modern/dsl/scope.rb +144 -0
  57. data/lib/modern/dsl/scope_settings.rb +39 -0
  58. data/lib/modern/dsl.rb +14 -0
  59. data/lib/modern/errors/error.rb +7 -0
  60. data/lib/modern/errors/setup_errors.rb +11 -0
  61. data/lib/modern/errors/web_errors.rb +83 -0
  62. data/lib/modern/errors.rb +3 -0
  63. data/lib/modern/redirect.rb +30 -0
  64. data/lib/modern/request.rb +34 -0
  65. data/lib/modern/response.rb +39 -0
  66. data/lib/modern/services.rb +17 -0
  67. data/lib/modern/struct.rb +25 -0
  68. data/lib/modern/types.rb +41 -0
  69. data/lib/modern/util/header_parsing.rb +27 -0
  70. data/lib/modern/util/trie_node.rb +53 -0
  71. data/lib/modern/version.rb +6 -0
  72. data/lib/modern.rb +8 -0
  73. data/manual/01-why_modern.md +115 -0
  74. data/modern.gemspec +54 -0
  75. metadata +439 -0
@@ -0,0 +1,115 @@
1
+ # What and Why? #
2
+ Modern is an API framework for Ruby web applications, built on top of Rack.
3
+
4
+ Which, by itself, isn't that much. There are a billion of these. You've got
5
+ Rails, Grape, Sinatra, and plenty more. And most of them are great! So, why then
6
+ did I feel compelled to write a new one?
7
+
8
+ A few reasons come to mind, and in describing them I hope to explain why Modern
9
+ exists and why you should use it.
10
+
11
+ ### You Shouldn't Need To Be An Expert To Do The Right Thing ###
12
+ You could call this "the right thing should be easy," too, but I feel like it's
13
+ important to dig into that a little more. Modern provides facilities to replace
14
+ a lot of the boilerplate and drudgery of other API frameworks with clean
15
+ tooling.
16
+
17
+ Modern cares about correctness. Unlike most frameworks, which have rolled their
18
+ own validation libraries (some of which are good--others of which, not so much),
19
+ Modern leverages the fantastic [dry-struct] and [dry-types] libraries to handle
20
+ easy and full-featured type declarations throughout its API. It'll test
21
+ validation of parameters and request bodies, doing the right thing (400 or 422,
22
+ as appropriate) when a problem arises--and, in development, it'll test your
23
+ response bodies against the return values you've specified, and alert you if
24
+ they don't match up.
25
+
26
+ Modern cares about security, too, and exposes to the user a simple mechanism for
27
+ securing APIs. It handles the plumbing work of pulling HTTP authorizations or
28
+ API keys out of various parameters, then hands them off to your code for proper
29
+ validation.
30
+
31
+ And Modern cares about how you're actually going to put it into production. Most
32
+ systems and frameworks are agnostic about things like request tracing or how
33
+ logging should be structured. Modern instead asserts that, yeah, you're going to
34
+ want to trace along requests to make sure everything's okay, so of course we'll
35
+ define a unique request ID (or use one if it's passed in via a HTTP request from
36
+ another service, allowing you to trace requests across many services). And
37
+ Modern also asserts that good, detailed logging is important, so its primary
38
+ logger emits structured, searchable logs courtesy of [Ougai].
39
+
40
+ ### Your Framework Shouldn't Obfuscate What You're Doing ###
41
+ A huge part of Ruby is how easy it is to build domain-specific languages to
42
+ describe the problems you're tackling. And that's fine, as far as it goes. But
43
+ the interplay between frameworks and libraries can make _what that DSL is doing_
44
+ more difficult than it needs to be to understand how your application works.
45
+
46
+ Modern is designed so that you don't _need_ a DSL. That isn't to say that a DSL
47
+ isn't useful (and `modern-dsl` is a project I'm working on as I go), but instead
48
+ that a simple, declarative object model doesn't have to be obfuscated by a
49
+ complex, sometimes even stateful (lookin' at you, Grape--carrying options
50
+ _forward_ onto the next route you declare is silly!) DSL.
51
+
52
+ Simple is good. Modern tries to be simple, and any DSL that wraps it will have
53
+ to reflect that.
54
+
55
+ ### OpenAPI Should Be First-Class ###
56
+ [OpenAPI] is awesome. I got the bug with Swagger 2.0 (now OpenAPI 2.0--the
57
+ naming is not why all of this is great) and realized that I'd wasted way too
58
+ much time building clients from scratch to talk to an API I'd knocked together
59
+ on the other end. Its tooling is great and getting better, with self-documenting
60
+ API tools and a number of generators to create clients in both dynamically typed
61
+ and statically typed languages.
62
+
63
+ Personally, I prefer to dynamically generate clients in dynamically typed
64
+ languages; [swagger-js] is kind of my thing. But reasonable people can differ.
65
+
66
+ The important thing here, though, is that Modern is designed around OpenAPI and
67
+ speaks its conventions "natively". The core object model of Modern (described in
68
+ detail later) maps easily to OpenAPI 3.0 and so an API designed along Modern's
69
+ "happy path" makes it easy to interconnect it with other systems you might run
70
+ across. You fire up your Modern app, it generates and serves an OpenAPI spec,
71
+ and you're off to the races.
72
+
73
+ ### Modern Should Be Portable ###
74
+ Obviously, I don't mean you're going to fire up Node and run `modern.rb`. But
75
+ Modern is intended to describe a fairly straightforward and _simple_ set of
76
+ behaviors that are OpenAPI-specific much more than they are Ruby-specific. It
77
+ should be eminently possible to do a side-by-side port of Modern to Node or to
78
+ Kotlin or to other languages in a way that provides baseline OpenAPI server
79
+ capabilities wherever you happen to be.
80
+
81
+ ## How Modern Works ##
82
+ Modern is a standard Rack-based application, run through a config.ru` file like
83
+ any other. There's plenty of great Rack documentation out there. Instead, let's
84
+ talk briefly about how Modern is structured, at the level you're likely to need
85
+ to know it.
86
+
87
+ The heart of your application is the **descriptor**. This object, and its children,
88
+ are an immutable declaration of "how this application runs". Routes, security
89
+ declarations, input/output converters--all of these are defined strictly by the
90
+ descriptor, which you can find in `Modern::Descriptor::Core`.
91
+
92
+ You'll also create a **configuration**, which should be an instance of type
93
+ `Modern::Configuration` or a subtype thereof if you'd like to incorporate your
94
+ own configuration data into the same object. These are operational concerns that
95
+ Modern needs to know about--whether or not to show backtraces in errors, whether
96
+ or not to validate response bodies on their way out the door, that sort of thing.
97
+
98
+ Lastly, you'll (optionally) define a set of **services**, which should be an
99
+ instance of `Modern::Services` or a subtype thereof. Here's where you'll provide
100
+ to your application the links to external "stuff", whether it's a logger or your
101
+ database or a client for a remote service. These services will be injected into
102
+ the scope of every route you write, making it easy to avoid global state or
103
+ unexpected side effects within your application.
104
+
105
+ Once you've got your descriptor, your configuration, and your services, you'll
106
+ pass them all to a constructor for `Modern::App`, which is the Rack interface
107
+ that handles your requests. It'll generate your OpenAPI documentation from your
108
+ descriptor and handle serving it, while also accepting incoming requests from
109
+ clients and dispatching them to the functional aspects of your descriptor.
110
+
111
+ [dry-struct]: http://dry-rb.org/gems/dry-struct
112
+ [dry-types]: http://dry-rb.org/gems/dry-types
113
+ [Ougai]: https://github.com/tilfin/ougai
114
+ [OpenAPI]: https://www.openapis.org
115
+ [swagger-js]: https://github.com/swagger-api/swagger-js
data/modern.gemspec ADDED
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "modern/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "modern"
9
+ spec.version = Modern::VERSION
10
+ spec.required_ruby_version = "~> 2.4"
11
+ spec.authors = ["Ed Ropple"]
12
+ spec.email = ["ed@edropple.com"]
13
+
14
+ spec.summary = "The OpenAPI-driven web framework for Ruby."
15
+ spec.homepage = "https://github.com/modern-project/modern-ruby"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.16"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+
28
+ spec.add_development_dependency "rack-test", "~> 0.8"
29
+ spec.add_development_dependency "rspec", "~> 3.7"
30
+
31
+ spec.add_development_dependency "pry"
32
+ spec.add_development_dependency "rcodetools"
33
+ spec.add_development_dependency "rubocop"
34
+ spec.add_development_dependency "ruby-debug-ide"
35
+
36
+ spec.add_development_dependency "openapi3_parser"
37
+
38
+ spec.add_runtime_dependency "mime-types", "~> 3.1"
39
+ spec.add_runtime_dependency "mime-types-data", "~> 3.2016"
40
+ spec.add_runtime_dependency "rack", "~> 2.0"
41
+
42
+ spec.add_runtime_dependency "content-type", "~> 0.0.1"
43
+ spec.add_runtime_dependency "http", "~> 3.0"
44
+
45
+ spec.add_runtime_dependency "deep_dup", "~> 0.0.3"
46
+ spec.add_runtime_dependency "deep_merge", "~> 1.2"
47
+ spec.add_runtime_dependency "diff-lcs", "~> 1.3"
48
+ spec.add_runtime_dependency "docile", "~> 1.3"
49
+ spec.add_runtime_dependency "dry-struct", "~> 0.4"
50
+ spec.add_runtime_dependency "dry-validation", "~> 0.11"
51
+ spec.add_runtime_dependency "ice_nine", "~> 0.11.2"
52
+ spec.add_runtime_dependency "ougai", "~> 1.5"
53
+ spec.add_runtime_dependency "snake_camel", "~> 1.1"
54
+ end
metadata ADDED
@@ -0,0 +1,439 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modern
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
5
+ platform: ruby
6
+ authors:
7
+ - Ed Ropple
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rcodetools
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby-debug-ide
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: openapi3_parser
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: mime-types
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '3.1'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.1'
153
+ - !ruby/object:Gem::Dependency
154
+ name: mime-types-data
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '3.2016'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '3.2016'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rack
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: content-type
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 0.0.1
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 0.0.1
195
+ - !ruby/object:Gem::Dependency
196
+ name: http
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '3.0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '3.0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: deep_dup
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: 0.0.3
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: 0.0.3
223
+ - !ruby/object:Gem::Dependency
224
+ name: deep_merge
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '1.2'
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '1.2'
237
+ - !ruby/object:Gem::Dependency
238
+ name: diff-lcs
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - "~>"
242
+ - !ruby/object:Gem::Version
243
+ version: '1.3'
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - "~>"
249
+ - !ruby/object:Gem::Version
250
+ version: '1.3'
251
+ - !ruby/object:Gem::Dependency
252
+ name: docile
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - "~>"
256
+ - !ruby/object:Gem::Version
257
+ version: '1.3'
258
+ type: :runtime
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - "~>"
263
+ - !ruby/object:Gem::Version
264
+ version: '1.3'
265
+ - !ruby/object:Gem::Dependency
266
+ name: dry-struct
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '0.4'
272
+ type: :runtime
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '0.4'
279
+ - !ruby/object:Gem::Dependency
280
+ name: dry-validation
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - "~>"
284
+ - !ruby/object:Gem::Version
285
+ version: '0.11'
286
+ type: :runtime
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - "~>"
291
+ - !ruby/object:Gem::Version
292
+ version: '0.11'
293
+ - !ruby/object:Gem::Dependency
294
+ name: ice_nine
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - "~>"
298
+ - !ruby/object:Gem::Version
299
+ version: 0.11.2
300
+ type: :runtime
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - "~>"
305
+ - !ruby/object:Gem::Version
306
+ version: 0.11.2
307
+ - !ruby/object:Gem::Dependency
308
+ name: ougai
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - "~>"
312
+ - !ruby/object:Gem::Version
313
+ version: '1.5'
314
+ type: :runtime
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - "~>"
319
+ - !ruby/object:Gem::Version
320
+ version: '1.5'
321
+ - !ruby/object:Gem::Dependency
322
+ name: snake_camel
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - "~>"
326
+ - !ruby/object:Gem::Version
327
+ version: '1.1'
328
+ type: :runtime
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - "~>"
333
+ - !ruby/object:Gem::Version
334
+ version: '1.1'
335
+ description:
336
+ email:
337
+ - ed@edropple.com
338
+ executables: []
339
+ extensions: []
340
+ extra_rdoc_files: []
341
+ files:
342
+ - ".editorconfig"
343
+ - ".gitignore"
344
+ - ".rspec"
345
+ - ".rubocop.yml"
346
+ - CODE_OF_CONDUCT.md
347
+ - Gemfile
348
+ - LICENSE.txt
349
+ - README.md
350
+ - Rakefile
351
+ - TODOS.md
352
+ - bin/console
353
+ - bin/setup
354
+ - example/Gemfile
355
+ - example/Gemfile.lock
356
+ - example/config.ru
357
+ - example/example.rb
358
+ - lib/modern.rb
359
+ - lib/modern/app.rb
360
+ - lib/modern/app/error_handling.rb
361
+ - lib/modern/app/request_handling.rb
362
+ - lib/modern/app/request_handling/input_handling.rb
363
+ - lib/modern/app/request_handling/output_handling.rb
364
+ - lib/modern/app/request_handling/request_container.rb
365
+ - lib/modern/app/router.rb
366
+ - lib/modern/app/trie_router.rb
367
+ - lib/modern/capsule.rb
368
+ - lib/modern/configuration.rb
369
+ - lib/modern/core_ext/array.rb
370
+ - lib/modern/core_ext/hash.rb
371
+ - lib/modern/descriptor.rb
372
+ - lib/modern/descriptor/content.rb
373
+ - lib/modern/descriptor/converters.rb
374
+ - lib/modern/descriptor/converters/input/base.rb
375
+ - lib/modern/descriptor/converters/input/json.rb
376
+ - lib/modern/descriptor/converters/output/base.rb
377
+ - lib/modern/descriptor/converters/output/json.rb
378
+ - lib/modern/descriptor/converters/output/yaml.rb
379
+ - lib/modern/descriptor/core.rb
380
+ - lib/modern/descriptor/info.rb
381
+ - lib/modern/descriptor/parameters.rb
382
+ - lib/modern/descriptor/request_body.rb
383
+ - lib/modern/descriptor/response.rb
384
+ - lib/modern/descriptor/route.rb
385
+ - lib/modern/descriptor/security.rb
386
+ - lib/modern/descriptor/server.rb
387
+ - lib/modern/doc_generator/open_api3.rb
388
+ - lib/modern/doc_generator/open_api3/operations.rb
389
+ - lib/modern/doc_generator/open_api3/paths.rb
390
+ - lib/modern/doc_generator/open_api3/schema_default_types.rb
391
+ - lib/modern/doc_generator/open_api3/schemas.rb
392
+ - lib/modern/doc_generator/open_api3/security_schemes.rb
393
+ - lib/modern/dsl.rb
394
+ - lib/modern/dsl/info.rb
395
+ - lib/modern/dsl/response_builder.rb
396
+ - lib/modern/dsl/root.rb
397
+ - lib/modern/dsl/route_builder.rb
398
+ - lib/modern/dsl/scope.rb
399
+ - lib/modern/dsl/scope_settings.rb
400
+ - lib/modern/errors.rb
401
+ - lib/modern/errors/error.rb
402
+ - lib/modern/errors/setup_errors.rb
403
+ - lib/modern/errors/web_errors.rb
404
+ - lib/modern/redirect.rb
405
+ - lib/modern/request.rb
406
+ - lib/modern/response.rb
407
+ - lib/modern/services.rb
408
+ - lib/modern/struct.rb
409
+ - lib/modern/types.rb
410
+ - lib/modern/util/header_parsing.rb
411
+ - lib/modern/util/trie_node.rb
412
+ - lib/modern/version.rb
413
+ - manual/01-why_modern.md
414
+ - modern.gemspec
415
+ homepage: https://github.com/modern-project/modern-ruby
416
+ licenses:
417
+ - MIT
418
+ metadata: {}
419
+ post_install_message:
420
+ rdoc_options: []
421
+ require_paths:
422
+ - lib
423
+ required_ruby_version: !ruby/object:Gem::Requirement
424
+ requirements:
425
+ - - "~>"
426
+ - !ruby/object:Gem::Version
427
+ version: '2.4'
428
+ required_rubygems_version: !ruby/object:Gem::Requirement
429
+ requirements:
430
+ - - ">="
431
+ - !ruby/object:Gem::Version
432
+ version: '0'
433
+ requirements: []
434
+ rubyforge_project:
435
+ rubygems_version: 2.7.3
436
+ signing_key:
437
+ specification_version: 4
438
+ summary: The OpenAPI-driven web framework for Ruby.
439
+ test_files: []