lennarb 0.1.7 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3b1fe759bb5de90ef757201a4023c441a9c40146f31a318aecc5c5c08cd04bb
4
- data.tar.gz: 8137ee838ca5636d7013cbfa5aa5f7e83d66e3b28d3387255b702d82becd884a
3
+ metadata.gz: 3a9951f0d799cadd7b4c3025eeaa9b050dd3920524b0a256530b4c53bb924a74
4
+ data.tar.gz: 39e78cd19783b98bb9f88d064821207dbc506c94f6742b840bfc3e31ed6568e9
5
5
  SHA512:
6
- metadata.gz: 3216bc56c89485d3292b621dcdfb26082957bea1ecfc622107b2f631f86508d7eb5318ce5bc43889ccf0db59775dcefd34e7e4ac00f5b023f34c4f371bab83b9
7
- data.tar.gz: 944b432173eeeee78c2fc8d546ee74f6768ab3581a61babfdad27f8e54969afd96581259d8866126a3e6e26c2418f92355af8cc07d3aa215b0f9fb9a6bceccc0
6
+ metadata.gz: 9ec6a17703b76f22f9f24f1d356c8bf190ed351d1629deeffaf5b871d3ae5907130d90d9329cc9b51f859659c75732fdb034dc029d81c7faed324979e536b090
7
+ data.tar.gz: 5efe46152e8796c8f07d19d0117da18c7868f07bf472be060de06ae140ff6cccbf69daf9d0b0883584875e600ecf0855ec52cffbef253c277325cbdbd2363d72
data/changelog.md CHANGED
@@ -5,6 +5,27 @@ 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
+
8
29
  ## [0.1.7] - 2023-23-12
9
30
 
10
31
  ### Added
data/exe/lenna CHANGED
@@ -10,8 +10,6 @@
10
10
  #
11
11
  require 'lennarb'
12
12
 
13
- # Call the CLI to start the server
13
+ # Show the version
14
14
  #
15
- # @private `Since v0.1`
16
- #
17
- Lenna::Cli::App.run!(ARGV)
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.7'
6
+ class Lennarb
7
+ VERSION = '0.2.0'
8
8
 
9
9
  public_constant :VERSION
10
10
  end
data/lib/lennarb.rb CHANGED
@@ -1,46 +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'
16
19
 
17
- # Core extensions
18
- #
19
- require 'pathname'
20
+ class Lennarb
21
+ # Error class
22
+ #
23
+ class LennarbError < StandardError; end
20
24
 
21
- # Zeitwerk
22
- #
23
- require 'zeitwerk'
25
+ # @attribute [r] root
26
+ # @return [RouteNode]
27
+ #
28
+ attr_reader :root
24
29
 
25
- # Zeitwerk loader
26
- #
27
- Zeitwerk::Loader.new.tap do |loader|
28
- loader.inflector.inflect('Version' => 'VERSION')
29
- loader.push_dir(__dir__)
30
- loader.setup
31
- end
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
32
40
 
33
- # Lennarb module
34
- #
35
- module Lennarb
36
- module_function
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)
37
66
 
38
- # Lennarb root path
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
39
90
  #
40
- # @return [Pathname] the root path
91
+ # @return [void]
41
92
  #
42
- def root
43
- File.expand_path('..', __dir__)
44
- Pathname.new(File.expand_path('..', __dir__))
93
+ def add_route(path, http_method, block)
94
+ parts = SplitPath[path]
95
+ @root.add_route(parts, http_method, block)
45
96
  end
46
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.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aristóteles Coutinho
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-31 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
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.1'
27
- - !ruby/object:Gem::Dependency
28
- name: console
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.23'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.23'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rack
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -59,45 +45,33 @@ dependencies:
59
45
  - !ruby/object:Gem::Version
60
46
  version: 3.0.8
61
47
  - !ruby/object:Gem::Dependency
62
- name: zeitwerk
48
+ name: bake
63
49
  requirement: !ruby/object:Gem::Requirement
64
50
  requirements:
65
51
  - - "~>"
66
52
  - !ruby/object:Gem::Version
67
- version: '2.6'
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- version: 2.6.12
71
- type: :runtime
53
+ version: 0.18.2
54
+ type: :development
72
55
  prerelease: false
73
56
  version_requirements: !ruby/object:Gem::Requirement
74
57
  requirements:
75
58
  - - "~>"
76
59
  - !ruby/object:Gem::Version
77
- version: '2.6'
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- version: 2.6.12
60
+ version: 0.18.2
81
61
  - !ruby/object:Gem::Dependency
82
- name: bake
62
+ name: bundler
83
63
  requirement: !ruby/object:Gem::Requirement
84
64
  requirements:
85
65
  - - "~>"
86
66
  - !ruby/object:Gem::Version
87
- version: '0.18'
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- version: 0.18.2
67
+ version: '2.2'
91
68
  type: :development
92
69
  prerelease: false
93
70
  version_requirements: !ruby/object:Gem::Requirement
94
71
  requirements:
95
72
  - - "~>"
96
73
  - !ruby/object:Gem::Version
97
- version: '0.18'
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- version: 0.18.2
74
+ version: '2.2'
101
75
  - !ruby/object:Gem::Dependency
102
76
  name: covered
103
77
  requirement: !ruby/object:Gem::Requirement
@@ -112,6 +86,20 @@ dependencies:
112
86
  - - "~>"
113
87
  - !ruby/object:Gem::Version
114
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'
115
103
  - !ruby/object:Gem::Dependency
116
104
  name: puma
117
105
  requirement: !ruby/object:Gem::Requirement
@@ -126,6 +114,20 @@ dependencies:
126
114
  - - "~>"
127
115
  - !ruby/object:Gem::Version
128
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'
129
131
  - !ruby/object:Gem::Dependency
130
132
  name: rack-test
131
133
  requirement: !ruby/object:Gem::Requirement
@@ -177,27 +179,10 @@ extra_rdoc_files: []
177
179
  files:
178
180
  - changelog.md
179
181
  - exe/lenna
180
- - lib/lenna/application.rb
181
- - lib/lenna/cli/app.rb
182
- - lib/lenna/cli/commands/create_project.rb
183
- - lib/lenna/cli/commands/interface.rb
184
- - lib/lenna/cli/commands/start_server.rb
185
- - lib/lenna/cli/templates/application.erb
186
- - lib/lenna/cli/templates/config.ru.erb
187
- - lib/lenna/cli/templates/gemfile.erb
188
- - lib/lenna/middleware/app.rb
189
- - lib/lenna/middleware/default/error_handler.rb
190
- - lib/lenna/middleware/default/logging.rb
191
- - lib/lenna/middleware/default/reload.rb
192
- - lib/lenna/router.rb
193
- - lib/lenna/router/builder.rb
194
- - lib/lenna/router/cache.rb
195
- - lib/lenna/router/namespace_stack.rb
196
- - lib/lenna/router/request.rb
197
- - lib/lenna/router/response.rb
198
- - lib/lenna/router/route_matcher.rb
199
182
  - lib/lennarb.rb
200
- - lib/lennarb/array_extensions.rb
183
+ - lib/lennarb/request.rb
184
+ - lib/lennarb/response.rb
185
+ - lib/lennarb/route_node.rb
201
186
  - lib/lennarb/version.rb
202
187
  - license.md
203
188
  - readme.md
@@ -218,14 +203,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
203
  requirements:
219
204
  - - ">="
220
205
  - !ruby/object:Gem::Version
221
- version: '3.0'
206
+ version: '3.1'
222
207
  required_rubygems_version: !ruby/object:Gem::Requirement
223
208
  requirements:
224
209
  - - ">="
225
210
  - !ruby/object:Gem::Version
226
211
  version: '0'
227
212
  requirements: []
228
- rubygems_version: 3.4.10
213
+ rubygems_version: 3.5.3
229
214
  signing_key:
230
215
  specification_version: 4
231
216
  summary: A lightweight and experimental web framework for Ruby.