lennarb 0.1.5 → 0.1.6

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: 59a236423ff7acaaeec6bf3b3b2a7dd42bfbc704eac97f7e2c7aa0539ebc0f45
4
- data.tar.gz: 19b0a12ce5aa48f252c1ff342987b3c4e42073fe80a584dd983c3739321b316c
3
+ metadata.gz: 133bc5b7fbe787ae7bf9d17f79cddb09d75f3e1d12e99deff891edae698b109a
4
+ data.tar.gz: de9d4b466c30c19b1fd84e6d55c162f144904aa09d22d4bc874bb7291eb72ce8
5
5
  SHA512:
6
- metadata.gz: 4df198f477ac2fcb3c09efb95ad9ea2699d6a12051cc9bcacd56c65adfe6d7778eed6cc1e920d6df35141d4dbbbb5aab4dfcc4aaea00483666e836b114b9e5e3
7
- data.tar.gz: 03a57883380017a70be1974bd98cdd6df3bd851c1944f787db4d97aec1ddc0f8947f3fc8a3179d817585d5a8ce877454f52a539ab8b77403bafe4cdd0321d7c1
6
+ metadata.gz: 1aa540d8f1f3d7d82104f441f4d141249485597d34d80072bb2c5df38237ea2651dba35b4f2499f00be7c9d1a94755c2400aefbe102283ff5a0ea3341dc74e97
7
+ data.tar.gz: 5660b98b90c019ff4501076845668ddea45210e701d91eae9b99c38a36ee7605511903178e986239934078d22aa8d7156d6efe4c73560e5c4951d7c734fa6f77
data/changelog.md ADDED
@@ -0,0 +1,165 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.6] - 2023-21-12
9
+
10
+ ### Changed
11
+
12
+ - Update `README.md` with the new features. Move examples to `guides` folder.
13
+ - Replace `rubocop` to `standard` gem to lint the code.
14
+ - Move `puma` gem to development dependencies.
15
+ - Use tabs instead of spaces to indent the code.
16
+ - Add default middlewares to `Lennarb::Router` class. Now, the `Lennarb::Router` class has the following middlewares by default:
17
+
18
+ - `Lennarb::Middleware::Default::Logging`
19
+ - `Lennarb::Middleware::Default::ErrorHandling`
20
+
21
+ - Replace `assign_status` to `=` on Response
22
+
23
+ ```rb
24
+ response.status = 200
25
+ ```
26
+
27
+ - Rename `Lenna::Base` to `Lenna::Application` and accept a block to build the routes. Ex.
28
+
29
+ ```rb
30
+ Lenna::Application.new do |app|
31
+ app.get '/hello' do |req, res|
32
+ res.status = 200
33
+ res['Content-Type'] = 'text/plain'
34
+ res.body = 'Hello World'
35
+ end
36
+ app.post '/hello' do |req, res|
37
+ res.status = 200
38
+ res['Content-Type'] = 'text/plain'
39
+ res.body = 'Hello World'
40
+ end
41
+ end
42
+ ```
43
+
44
+ - The Middleware app now implements [Singleton](https://ruby-doc.org/stdlib-2.5.1/libdoc/singleton/rdoc/Singleton.html) pattern to manager state.
45
+
46
+ ### Added
47
+
48
+ - Add `standard` gem to lint the code.
49
+ - Add `maintenance` gropu to `Gemfile` with:
50
+ - Add `bake-gem` gem to run the tasks.
51
+ - Add `bake-modernize` gem to update the code to the latest Ruby version.
52
+ - Add `utopia-project` gem to generate the project.
53
+ - Add `bake-github-pages` to generate the GitHub Pages.
54
+ - Add `bake` gem to run the tasks.
55
+ - Add `puma` gem to run the development server.
56
+ - Add alias to `assign_header` to `[]=` on Response. Now, you can use:
57
+
58
+ ```rb
59
+ response['Content-Type'] = 'application/json'
60
+ ```
61
+
62
+ - Add alias to `assign_body` to `:body=` on Response. Now, you can use:
63
+
64
+ ```rb
65
+ response.body = 'Hello World'
66
+ ```
67
+
68
+ - Add alias to `assign_params` to `:params=` on Request. Now, you can use:
69
+
70
+ ```rb
71
+ request.params = { name: 'John' }
72
+ ```
73
+
74
+ ### Removed
75
+
76
+ - Remove `listen` method to run development server. Now, you must be use `.config.ru` file to run the development server. Ex.
77
+
78
+ ```rb
79
+ # .config.ru
80
+
81
+ require 'lennarb'
82
+
83
+ 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
94
+ end
95
+
96
+ run app
97
+ ```
98
+
99
+ - Remove Rakefile. Now, you must be use `bake` gem to run the tasks. Ex.
100
+
101
+ ```sh
102
+ bundle exec bake test
103
+ ```
104
+
105
+ ## Bug Fixes
106
+
107
+ - Fix default middlewares to `Lennarb::Router` class. Now, the `Lennarb::Router` class has the following middlewares by default:
108
+ - `Lennarb::Middleware::Default::Logging`
109
+ - `Lennarb::Middleware::Default::ErrorHandling`
110
+
111
+ ## [0.1.5] - 2023-25-11
112
+
113
+ ### Added
114
+
115
+ - Add `assign_params` method to Request class
116
+
117
+ ## [0.1.4] - 2023-25-11
118
+
119
+ ### Fixed
120
+
121
+ - Internal docmentation methods
122
+ - Fix `post_params` from Resquest router class
123
+
124
+ ### Added
125
+
126
+ - Add basic documentation for usage. See [README.md](README.md) for more details.
127
+
128
+ ## [0.1.3] - 2023-24-11
129
+
130
+ ## [0.1.2] - 2023-23-11
131
+
132
+ ### Added
133
+
134
+ - Implemented a specific error handler for Content-Type related errors, enhancing the system's ability to respond appropriately based on whether the request Content-Type is JSON or HTML.
135
+
136
+ ### Removed
137
+
138
+ - Removed the debug gem from development dependencies, streamlining the development environment setup.
139
+
140
+ ### Fixed
141
+
142
+ - Fixed a bug that prevented the correct reading of the Content-Type header in requests, ensuring proper handling of content types.
143
+
144
+ ## [0.1.1] - 2023-23-11
145
+
146
+ ### Added
147
+
148
+ - Introduced `Array.wrap` extension to the `Array` class for more reliable conversion of objects to arrays within the Lennarb router environment. This method ensures consistent array wrapping of single objects and `nil` values.
149
+
150
+ ### Changed
151
+
152
+ - Refactored the `put_header` method to use the `Array.wrap` method for more predictable header value handling.
153
+ - Renamed methods to have a consistent `assign_` prefix to standardize the API interface:
154
+ - `put_header` to `assign_header`
155
+ - `write_body` to `assign_body`
156
+ - `set_params` to `assign_params`
157
+ - `update_status` to `assign_status`
158
+
159
+ ### Deprecated
160
+
161
+ ### Removed
162
+
163
+ ### Fixed
164
+
165
+ ### Security
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ # Internal dependencies
7
+ #
8
+ require 'lenna/middleware/default/error_handler'
9
+ require 'lenna/middleware/default/logging'
10
+ require 'lenna/router'
11
+
12
+ # The Lenna module is used to namespace the framework.
13
+ #
14
+ # @public
15
+ #
16
+ module Lenna
17
+ # The base class is used to start the server.
18
+ #
19
+ # @public
20
+ #
21
+ class Application < Router
22
+ # Initialize the base class
23
+ #
24
+ # @yield { ... } the block to be evaluated in the context of the instance.
25
+ #
26
+ # @return [void | Application] Returns the instance if a block is given.
27
+ #
28
+ def initialize
29
+ super
30
+ yield self if block_given?
31
+ end
32
+ end
33
+
34
+ # The base module is used to include the base class.
35
+ #
36
+ # @public
37
+ #
38
+ module Base
39
+ def self.included(base)
40
+ base.extend(ClassMethods)
41
+ end
42
+
43
+ module ClassMethods
44
+ # Initialize the base module
45
+ #
46
+ # @return [Lenna::Application] Returns the instance.
47
+ #
48
+ # @public
49
+ #
50
+ def app = @app ||= Lenna::Application.new
51
+ end
52
+ end
53
+ end
@@ -1,103 +1,118 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ require 'singleton'
7
+
3
8
  module Lenna
4
- module Middleware
5
- # The MiddlewareManager class is responsible for managing the middlewares.
6
- #
7
- # @attr mutex [Mutex] the mutex used to synchronize the
8
- # access to the global middlewares and
9
- # the middleware chains cache.
10
- # @attr global_middlewares [Array] the global middlewares
11
- # @attr middleware_chains_cache [Hash] the middleware chains cache
12
- #
13
- # @note Middleware chains are cached by action.
14
- # The middlewares that are added to a specific route are added to the
15
- # global middlewares.
16
- #
17
- # @api private
18
- #
19
- # @since 0.1.0
20
- class App
21
- # @return [Mutex] the mutex used to synchronize the access to the global
22
- attr_reader :global_middlewares
9
+ module Middleware
10
+ # The MiddlewareManager class is responsible for managing the middlewares.
11
+ #
12
+ # @attr global_middlewares [Array] the global middlewares
13
+ # @attr middleware_chains_cache [Hash] the middleware chains cache
14
+ #
15
+ # Middleware chains are cached by action.
16
+ # The middlewares that are added to a specific route are added to the
17
+ # global middlewares.
18
+ #
19
+ # @private Since `v0.1.0`
20
+ #
21
+ class App
22
+ include Singleton
23
+
24
+ # @return [Array] the global middlewares.
25
+ #
26
+ attr_accessor :global_middlewares
27
+ # @return [Hash] the middleware chains cache.
28
+ #
29
+ attr_accessor :middleware_chains_cache
23
30
 
24
- # @return [Hash] the middleware chains cache
25
- attr_reader :middleware_chains_cache
31
+ # This method will initialize the global middlewares and the
32
+ # middleware chains cache.
33
+ #
34
+ # @return [void]
35
+ #
36
+ def initialize
37
+ @global_middlewares = []
38
+ @middleware_chains_cache = {}
39
+ end
26
40
 
27
- # This method will initialize the global middlewares and the
28
- # middleware chains cache.
29
- #
30
- # @return [void]
31
- #
32
- # @since 0.1.0
33
- def initialize
34
- @mutex = ::Mutex.new
35
- @global_middlewares = []
36
- @middleware_chains_cache = {}
37
- end
41
+ # This method is used to reset the global middlewares and the middleware
42
+ # chains cache.
43
+ #
44
+ # @return [void]
45
+ #
46
+ def reset!
47
+ @global_middlewares = []
48
+ @middleware_chains_cache = {}
49
+ end
38
50
 
39
- # This method is used to add a middleware to the global middlewares.
40
- # @param middlewares [Array] the middlewares to be used
41
- # @return [void]
42
- #
43
- # @since 0.1.0
44
- def use(middlewares)
45
- @mutex.synchronize do
46
- @global_middlewares += Array(middlewares)
47
- @middleware_chains_cache = {}
48
- end
49
- end
51
+ # This method is used to add a middleware to the global middlewares.
52
+ # @parameter middlewares [Array] the middlewares to be used
53
+ # @return [void]
54
+ #
55
+ def use(middlewares)
56
+ @global_middlewares += Array(middlewares)
57
+ @middleware_chains_cache = {}
58
+ end
50
59
 
51
- # This method is used to fetch or build the middleware chain for the given
52
- # action and route middlewares.
53
- #
54
- # @param action [Proc] the action to be executed
55
- # @param route_middlewares [Array] the middlewares to be used
56
- # @return [Proc] the middleware chain
57
- #
58
- # @see #build_middleware_chain
59
- #
60
- # @since 0.1.0
61
- def fetch_or_build_middleware_chain(action, route_middlewares)
62
- middleware_signature = action.object_id.to_s
60
+ # This method is used to fetch or build the middleware chain for the given
61
+ # action and route middlewares.
62
+ #
63
+ # @parameter action [Proc] the action to be executed
64
+ # @parameter route_middlewares [Array] the middlewares to be used
65
+ # @return [Proc] the middleware chain
66
+ #
67
+ #
68
+ def fetch_or_build_middleware_chain(
69
+ action,
70
+ route_middlewares,
71
+ http_method: nil,
72
+ path: nil
73
+ )
74
+ signature =
75
+ if http_method && path
76
+ [http_method, path, route_middlewares].hash.to_s
77
+ else
78
+ ['global', route_middlewares].hash.to_s
79
+ end
63
80
 
64
- @mutex.synchronize do
65
- @middleware_chains_cache[middleware_signature] ||=
66
- build_middleware_chain(action, route_middlewares)
67
- end
68
- end
81
+ @middleware_chains_cache[signature] ||=
82
+ build_middleware_chain(action, route_middlewares)
83
+ end
69
84
 
70
- # This method is used to build the middleware chain for the given action
71
- # and middlewares.
72
- #
73
- # @param action [Proc] the action to be executed
74
- # @param middlewares [Array] the middlewares to be used
75
- # @return [Proc] the middleware chain
76
- #
77
- # @since 0.1.0
78
- #
79
- # @example Given the action:
80
- # `->(req, res) { res << 'Hello' }` and the
81
- # middlewares [mw1, mw2], the middleware
82
- # chain will be:
83
- # mw1 -> mw2 -> action
84
- # The action will be the last middleware in the
85
- # chain.
86
- def build_middleware_chain(action, middlewares)
87
- all_middlewares = @global_middlewares + Array(middlewares)
85
+ # This method is used to build the middleware chain for the given action
86
+ # and middlewares.
87
+ #
88
+ # @parameter action [Proc] the action to be executed
89
+ # @parameter middlewares [Array] the middlewares to be used
90
+ # @return [Proc] the middleware chain
91
+ #
92
+ # ex.
93
+ # Given the action:
94
+ # `->(req, res) { res << 'Hello' }` and the
95
+ # middlewares [mw1, mw2], the middleware
96
+ # chain will be:
97
+ # mw1 -> mw2 -> action
98
+ # The action will be the last middleware in the
99
+ # chain.
100
+ #
101
+ def build_middleware_chain(action, middlewares)
102
+ all_middlewares = (@global_middlewares + Array(middlewares))
88
103
 
89
- all_middlewares.reverse.reduce(action) do |next_middleware, middleware|
90
- ->(req, res) {
91
- middleware.call(
92
- req,
93
- res,
94
- -> {
95
- next_middleware.call(req, res)
96
- }
97
- )
98
- }
99
- end
100
- end
101
- end
102
- end
104
+ all_middlewares.reverse.reduce(action) do |next_middleware, middleware|
105
+ ->(req, res) {
106
+ middleware.call(
107
+ req,
108
+ res,
109
+ -> {
110
+ next_middleware.call(req, res)
111
+ }
112
+ )
113
+ }
114
+ end
115
+ end
116
+ end
117
+ end
103
118
  end