lennarb 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 133bc5b7fbe787ae7bf9d17f79cddb09d75f3e1d12e99deff891edae698b109a
4
- data.tar.gz: de9d4b466c30c19b1fd84e6d55c162f144904aa09d22d4bc874bb7291eb72ce8
3
+ metadata.gz: 3a9951f0d799cadd7b4c3025eeaa9b050dd3920524b0a256530b4c53bb924a74
4
+ data.tar.gz: 39e78cd19783b98bb9f88d064821207dbc506c94f6742b840bfc3e31ed6568e9
5
5
  SHA512:
6
- metadata.gz: 1aa540d8f1f3d7d82104f441f4d141249485597d34d80072bb2c5df38237ea2651dba35b4f2499f00be7c9d1a94755c2400aefbe102283ff5a0ea3341dc74e97
7
- data.tar.gz: 5660b98b90c019ff4501076845668ddea45210e701d91eae9b99c38a36ee7605511903178e986239934078d22aa8d7156d6efe4c73560e5c4951d7c734fa6f77
6
+ metadata.gz: 9ec6a17703b76f22f9f24f1d356c8bf190ed351d1629deeffaf5b871d3ae5907130d90d9329cc9b51f859659c75732fdb034dc029d81c7faed324979e536b090
7
+ data.tar.gz: 5efe46152e8796c8f07d19d0117da18c7868f07bf472be060de06ae140ff6cccbf69daf9d0b0883584875e600ecf0855ec52cffbef253c277325cbdbd2363d72
data/changelog.md CHANGED
@@ -5,6 +5,72 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] - 2024-08-01
9
+
10
+ ### Removed
11
+
12
+ - Remove `zeitwerk` gem to load the files in the project.
13
+ - Remove `console` gem to print the logs in the console.
14
+ - Remove `Lenna` module. Now, the `Lennarb` class is the main class of the project.
15
+ - Remove `Middleware` module.
16
+ - Remove `CLI` module.
17
+ - Remove `Cache` module
18
+
19
+ ### Changed
20
+
21
+ - Change `Lennarb::Application` class to `Lennarb` class.
22
+ - Request class and Response class now are in `Lennarb` class
23
+ - Change `Lennarb::Router` class to `Lennarb` class
24
+
25
+ ### Fixed
26
+
27
+ - Improve performance of the RPS (Requests per second), memory and CPU usage. Now the performance is similar to the [Roda](https://github.com/jeremyevans/roda/tree/master).
28
+
29
+ ## [0.1.7] - 2023-23-12
30
+
31
+ ### Added
32
+
33
+ - Add `console` gem to print the logs in the console.
34
+
35
+ - Add CLI module to:
36
+ - Create a new project with `lennarb new` command.
37
+ - Run the server with `lennarb server` command.
38
+
39
+ - Add simple guide to create and run a project with Lennarb. See [guides/command-line/readme.md](guides/command-line/readme.md) for more details.
40
+
41
+ - Add `Reload` middleware to reload the application in development environment. You can import and use this middleware in your application. Ex.
42
+
43
+ ```rb
44
+ # app.rb
45
+
46
+ require 'lenna/middleware/default/reload'
47
+
48
+ app = Lenna::Application.new
49
+
50
+ app.use Lenna::Middleware::Default::Reload
51
+ ```
52
+
53
+ In the next version, this middleware will be available by default in development environment.
54
+
55
+ - Add `root` method to `Lennarb` module to get the root path of the project. Ex.
56
+
57
+ ```rb
58
+ # app.rb
59
+
60
+ Lennarb.root.join('app.rb')
61
+ # => /home/user/project/app.rb
62
+ ```
63
+
64
+ - Add `zeitwerk` gem to load the files in the project.
65
+
66
+ ### Remove
67
+
68
+ - Remove `Logging` and `ErrorHandling` middlewares from any environment. Now, theses middlewares are only available in development environment.
69
+
70
+ ### Changed
71
+
72
+ - Change log level to `fatal` in test environment.
73
+
8
74
  ## [0.1.6] - 2023-21-12
9
75
 
10
76
  ### Changed
@@ -81,16 +147,16 @@ request.params = { name: 'John' }
81
147
  require 'lennarb'
82
148
 
83
149
  app = Lennarb::Application.new do |app|
84
- app.get '/hello' do |req, res|
85
- res.status = 200
86
- res['Content-Type'] = 'text/plain'
87
- res.body = 'Hello World'
88
- end
89
- app.post '/hello' do |req, res|
90
- res.status = 200
91
- res['Content-Type'] = 'text/plain'
92
- res.body = 'Hello World'
93
- end
150
+ app.get '/hello' do |req, res|
151
+ res.status = 200
152
+ res['Content-Type'] = 'text/plain'
153
+ res.body = 'Hello World'
154
+ end
155
+ app.post '/hello' do |req, res|
156
+ res.status = 200
157
+ res['Content-Type'] = 'text/plain'
158
+ res.body = 'Hello World'
159
+ end
94
160
  end
95
161
 
96
162
  run app
data/exe/lenna ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Released under the MIT License.
5
+ # Copyright, 2023, by Aristóteles Coutinho.
6
+
7
+ # Require the main file
8
+ #
9
+ # @private `Since v0.1`
10
+ #
11
+ require 'lennarb'
12
+
13
+ # Show the version
14
+ #
15
+ puts Lennarb::VERSION
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
+
6
+ class Lennarb
7
+ class Request < Rack::Request
8
+ # Initialize the request object
9
+ #
10
+ # @parameter [Hash] env
11
+ # @parameter [Hash] route_params
12
+ #
13
+ # @return [Request]
14
+ #
15
+ def initialize(env, route_params = {})
16
+ super(env)
17
+ @route_params = route_params
18
+ end
19
+
20
+ # Get the request body
21
+ #
22
+ # @return [String]
23
+ def params
24
+ @params ||= super.merge(@route_params)
25
+ end
26
+
27
+ private
28
+
29
+ # Get the query string
30
+ #
31
+ # @return [String]
32
+ #
33
+ def query_params
34
+ @query_params ||= Rack::Utils.parse_nested_query(query_string)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
+
6
+ class Lennarb
7
+ class Response
8
+ # @!attribute [rw] status
9
+ # @return [Integer]
10
+ #
11
+ attr_accessor :status
12
+
13
+ # @!attribute [r] body
14
+ # @return [Array]
15
+ #
16
+ attr_reader :body
17
+
18
+ # @!attribute [r] headers
19
+ # @return [Hash]
20
+ #
21
+ attr_reader :headers
22
+
23
+ # @!attribute [r] length
24
+ # @return [Integer]
25
+ #
26
+ attr_reader :length
27
+
28
+ # Constants
29
+ #
30
+ LOCATION = 'location'
31
+ private_constant :LOCATION
32
+
33
+ CONTENT_TYPE = 'content-type'
34
+ private_constant :CONTENT_TYPE
35
+
36
+ CONTENT_LENGTH = 'content-length'
37
+ private_constant :CONTENT_LENGTH
38
+
39
+ ContentType = { HTML: 'text/html', TEXT: 'text/plain', JSON: 'application/json' }.freeze
40
+ private_constant :ContentType
41
+
42
+ # Initialize the response object
43
+ #
44
+ # @return [Response]
45
+ #
46
+ def initialize
47
+ @status = 404
48
+ @headers = {}
49
+ @body = []
50
+ @length = 0
51
+ end
52
+
53
+ # Set the response header
54
+ #
55
+ # @parameter [String] key
56
+ #
57
+ # @return [String] value
58
+ #
59
+ def [](key)
60
+ @headers[key]
61
+ end
62
+
63
+ # Get the response header
64
+ #
65
+ # @parameter [String] key
66
+ # @parameter [String] value
67
+ #
68
+ # @return [String] value
69
+ #
70
+ def []=(key, value)
71
+ @headers[key] = value
72
+ end
73
+
74
+ # Write to the response body
75
+ #
76
+ # @parameter [String] str
77
+ #
78
+ # @return [String] str
79
+ #
80
+ def write(str)
81
+ str = str.to_s
82
+ @length += str.bytesize
83
+ @headers[CONTENT_LENGTH] ||= @length.to_s
84
+ @body << str
85
+ end
86
+
87
+ # Set the response type to text
88
+ #
89
+ # @parameter [String] str
90
+ #
91
+ # @return [String] str
92
+ #
93
+ def text(str)
94
+ @headers[CONTENT_TYPE] = ContentType[:TEXT]
95
+ write(str)
96
+ end
97
+
98
+ # Set the response type to html
99
+ #
100
+ # @parameter [String] str
101
+ #
102
+ # @return [String] str
103
+ #
104
+ def html(str)
105
+ @headers[CONTENT_TYPE] = ContentType[:HTML]
106
+ write(str)
107
+ end
108
+
109
+ # Set the response type to json
110
+ #
111
+ # @parameter [String] str
112
+ #
113
+ # @return [String] str
114
+ #
115
+ def json(str)
116
+ @headers[CONTENT_TYPE] = ContentType[:JSON]
117
+ write(str)
118
+ end
119
+
120
+ # Redirect the response
121
+ #
122
+ # @parameter [String] path
123
+ # @parameter [Integer] status, default: 302
124
+ #
125
+ def redirect(path, status = 302)
126
+ @headers[LOCATION] = path
127
+ @status = status
128
+ end
129
+
130
+ # Finish the response
131
+ #
132
+ # @return [Array] response
133
+ #
134
+ def finish
135
+ [@status, @headers, @body]
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
+
6
+ class Lennarb
7
+ class RouteNode
8
+ attr_accessor :children, :blocks, :param_key
9
+
10
+ # Initialize the route node
11
+ #
12
+ # @return [RouteNode]
13
+ #
14
+ def initialize
15
+ @children = {}
16
+ @blocks = {}
17
+ @param_key = nil
18
+ end
19
+
20
+ # Add a route to the route node
21
+ #
22
+ # @parameter [Array] parts
23
+ # @parameter [String] http_method
24
+ # @parameter [Proc] block
25
+ #
26
+ # @return [void]
27
+ #
28
+ def add_route(parts, http_method, block)
29
+ current_node = self
30
+
31
+ parts.each do |part|
32
+ if part.start_with?(':')
33
+ key = :param
34
+ current_node.children[key] ||= RouteNode.new
35
+ current_node = current_node.children[key]
36
+ current_node.param_key = part[1..].to_sym
37
+ else
38
+ key = part
39
+ current_node.children[key] ||= RouteNode.new
40
+ current_node = current_node.children[key]
41
+ end
42
+ end
43
+
44
+ current_node.blocks[http_method] = block
45
+ end
46
+
47
+ # Match a route to the route node
48
+ #
49
+ # @parameter [Array] parts
50
+ # @parameter [String] http_method
51
+ #
52
+ # @return [Array]
53
+ #
54
+ def match_route(parts, http_method)
55
+ current_node = self
56
+ params = {}
57
+
58
+ parts.each do |part|
59
+ return [nil, nil] unless current_node.children.key?(part) || current_node.children[:param]
60
+
61
+ if current_node.children.key?(part)
62
+ current_node = current_node.children[part]
63
+ else
64
+ param_node = current_node.children[:param]
65
+ params[param_node.param_key] = part
66
+ current_node = param_node
67
+ end
68
+ end
69
+
70
+ [current_node.blocks[http_method], params]
71
+ end
72
+ end
73
+ end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Aristóteles Coutinho.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
5
 
6
- module Lennarb
7
- VERSION = '0.1.6'
6
+ class Lennarb
7
+ VERSION = '0.2.0'
8
8
 
9
9
  public_constant :VERSION
10
10
  end
data/lib/lennarb.rb CHANGED
@@ -1,15 +1,97 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Aristóteles Coutinho.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
5
 
6
6
  ENV['RACK_ENV'] ||= 'development'
7
7
 
8
- # Extension for Array class
8
+ # Core extensions
9
9
  #
10
- require 'lennarb/array_extensions'
10
+ require 'pathname'
11
+ require 'rack'
11
12
 
12
13
  # Base class for Lennarb
13
14
  #
14
- require 'lenna/application'
15
- require 'lennarb/version'
15
+ require_relative 'lennarb/request'
16
+ require_relative 'lennarb/response'
17
+ require_relative 'lennarb/route_node'
18
+ require_relative 'lennarb/version'
19
+
20
+ class Lennarb
21
+ # Error class
22
+ #
23
+ class LennarbError < StandardError; end
24
+
25
+ # @attribute [r] root
26
+ # @return [RouteNode]
27
+ #
28
+ attr_reader :root
29
+
30
+ # Initialize the application
31
+ #
32
+ # @yield { ... } The application
33
+ #
34
+ # @return [Lennarb]
35
+ #
36
+ def initialize
37
+ @root = RouteNode.new
38
+ yield self if block_given?
39
+ end
40
+
41
+ # Split a path into parts
42
+ #
43
+ # @parameter [String] path
44
+ #
45
+ # @return [Array] parts. Ex. ['users', ':id']
46
+ #
47
+ SplitPath = ->(path) { path.split('/').reject(&:empty?) }
48
+ private_constant :SplitPath
49
+
50
+ # Call the application
51
+ #
52
+ # @parameter [Hash] env
53
+ #
54
+ # @return [Array] response
55
+ #
56
+ def call(env)
57
+ res = Response.new
58
+ http_method = env.fetch('REQUEST_METHOD').to_sym
59
+ parts = SplitPath[env.fetch('PATH_INFO')]
60
+
61
+ block, params = @root.match_route(parts, http_method)
62
+ return [404, { 'content-type' => 'text/plain' }, ['Not Found']] unless block
63
+
64
+ req = Request.new(env, params)
65
+ instance_exec(req, res, &block)
66
+
67
+ res.finish
68
+ end
69
+
70
+ # Add a routes
71
+ #
72
+ # @parameter [String] path
73
+ # @parameter [Proc] block
74
+ #
75
+ # @return [void]
76
+ #
77
+ def get(path, &block) = add_route(path, :GET, block)
78
+ def post(path, &block) = add_route(path, :POST, block)
79
+ def put(path, &block) = add_route(path, :PUT, block)
80
+ def patch(path, &block) = add_route(path, :PATCH, block)
81
+ def delete(path, &block) = add_route(path, :DELETE, block)
82
+
83
+ private
84
+
85
+ # Add a route
86
+ #
87
+ # @parameter [String] path
88
+ # @parameter [String] http_method
89
+ # @parameter [Proc] block
90
+ #
91
+ # @return [void]
92
+ #
93
+ def add_route(path, http_method, block)
94
+ parts = SplitPath[path]
95
+ @root.add_route(parts, http_method, block)
96
+ end
97
+ end
data/license.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2023, by Aristóteles Coutinho.
3
+ Copyright, 2023-2024, by Aristóteles Coutinho.
4
+ Copyright, 2023, by aristotelesbr.
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
data/readme.md CHANGED
@@ -1,26 +1,43 @@
1
1
  # Lennarb
2
2
 
3
- Lennarb is a experimental lightweight, fast, and modular web framework for Ruby based on Rack.
3
+ Lennarb is a lightweight, fast, and modular web framework for Ruby based on Rack. The **Lennarb** supports Ruby (MRI) 3.0+
4
4
 
5
- ## Usage
5
+ **Basic Usage**
6
+
7
+ ```ruby
8
+ require "lennarb"
9
+
10
+ Lennarb.new do |router|
11
+ router.get("/hello/:name") do |req, res|
12
+ name = req.params[:name]
13
+ res.html("Hello, #{name}!")
14
+ end
15
+ end
16
+ ```
6
17
 
7
- Please see the [project documentation](https://aristotelesbr.github.io/lennarb) for more details.
18
+ ## Performance
8
19
 
9
- - [Getting Started](https://aristotelesbr.github.io/lennarbguides/getting-started/index) - This guide show you how to use the `lennarb`
20
+ ### 1. Requests per Second (RPS)
10
21
 
11
- - [Middlewares](https://aristotelesbr.github.io/lennarbguides/middlewares/index) - This guide shows how to use middlewares in Lennarb.
22
+ | Position | Application | 10 RPS | 100 RPS | 1.000 RPS | 10.000 RPS |
23
+ | -------- | ----------- | ---------- | ---------- | --------- | ---------- |
24
+ | 1 | Lenna | 126.252,36 | 108.086,55 | 87.111,91 | 68.460,64 |
25
+ | 2 | Roda | 123.360,37 | 88.380,56 | 66.990,77 | 48.108,29 |
26
+ | 3 | Syro | 114.105,38 | 80.909,39 | 61.415,86 | 46.639,81 |
27
+ | 4 | Hanami-API | 68.089,18 | 52.851,88 | 40.801,78 | 27.996,00 |
12
28
 
13
- - [Namespace routes](https://aristotelesbr.github.io/lennarbguides/namespace-routes/index) - This guide show you how to use namespace routes.
29
+ This table ranks the routers by the number of requests they can process per second. Higher numbers indicate better performance.
30
+
31
+ Plese see [Performance](https://aristotelesbr.github.io/lennarb/guides/performance/index.html) for more information.
32
+
33
+ ## Usage
14
34
 
15
- ## Contributing
35
+ - [Getting Started](https://aristotelesbr.github.io/lennarb/guides/getting-started/index) - This guide covers getting up and running with **Lennarb**.
16
36
 
17
- We welcome contributions to this project.
37
+ - [Performance](https://aristotelesbr.github.io/lennarb/guides/performance/index.html) - The **Lennarb** is very fast. The following benchmarks were performed on a MacBook Pro (Retina, 13-inch, Early 2013) with 2,7 GHz Intel Core i7 and 8 GB 1867 MHz DDR3. Based on [jeremyevans/r10k](https://github.com/jeremyevans/r10k) using the following [template build](static/r10k/build/lennarb.rb).
18
38
 
19
- 1. Fork it.
20
- 2. Create your feature branch (`git checkout -b my-new-feature`).
21
- 3. Commit your changes (`git commit -am 'Add some feature'`).
22
- 4. Push to the branch (`git push origin my-new-feature`).
23
- 5. Create new Pull Request.
39
+ - [Response](https://aristotelesbr.github.io/lennarb/guides/response/index.html) - This is the response guide.
40
+ The `res` object is used to send a response to the client. The Lennarb use a custom response object to send responses to the client. The `res` object is an instance of `Lennarb::Response`.
24
41
 
25
42
  ### Developer Certificate of Origin
26
43
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lennarb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aristóteles Coutinho
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-21 00:00:00.000000000 Z
11
+ date: 2024-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -48,16 +48,30 @@ dependencies:
48
48
  name: bake
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - ">="
51
+ - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: 0.18.2
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - ">="
58
+ - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: 0.18.2
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.2'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.2'
61
75
  - !ruby/object:Gem::Dependency
62
76
  name: covered
63
77
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +86,20 @@ dependencies:
72
86
  - - "~>"
73
87
  - !ruby/object:Gem::Version
74
88
  version: 0.25.1
89
+ - !ruby/object:Gem::Dependency
90
+ name: minitest
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '5.20'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '5.20'
75
103
  - !ruby/object:Gem::Dependency
76
104
  name: puma
77
105
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +114,20 @@ dependencies:
86
114
  - - "~>"
87
115
  - !ruby/object:Gem::Version
88
116
  version: '6.4'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rake
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '13.0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '13.0'
89
131
  - !ruby/object:Gem::Dependency
90
132
  name: rack-test
91
133
  requirement: !ruby/object:Gem::Requirement
@@ -130,24 +172,17 @@ dependencies:
130
172
  version: 0.33.0
131
173
  description:
132
174
  email:
133
- executables: []
175
+ executables:
176
+ - lenna
134
177
  extensions: []
135
178
  extra_rdoc_files: []
136
179
  files:
137
180
  - changelog.md
138
- - lib/lenna/application.rb
139
- - lib/lenna/middleware/app.rb
140
- - lib/lenna/middleware/default/error_handler.rb
141
- - lib/lenna/middleware/default/logging.rb
142
- - lib/lenna/router.rb
143
- - lib/lenna/router/builder.rb
144
- - lib/lenna/router/cache.rb
145
- - lib/lenna/router/namespace_stack.rb
146
- - lib/lenna/router/request.rb
147
- - lib/lenna/router/response.rb
148
- - lib/lenna/router/route_matcher.rb
181
+ - exe/lenna
149
182
  - lib/lennarb.rb
150
- - lib/lennarb/array_extensions.rb
183
+ - lib/lennarb/request.rb
184
+ - lib/lennarb/response.rb
185
+ - lib/lennarb/route_node.rb
151
186
  - lib/lennarb/version.rb
152
187
  - license.md
153
188
  - readme.md
@@ -168,14 +203,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
203
  requirements:
169
204
  - - ">="
170
205
  - !ruby/object:Gem::Version
171
- version: '3.0'
206
+ version: '3.1'
172
207
  required_rubygems_version: !ruby/object:Gem::Requirement
173
208
  requirements:
174
209
  - - ">="
175
210
  - !ruby/object:Gem::Version
176
211
  version: '0'
177
212
  requirements: []
178
- rubygems_version: 3.5.1
213
+ rubygems_version: 3.5.3
179
214
  signing_key:
180
215
  specification_version: 4
181
216
  summary: A lightweight and experimental web framework for Ruby.