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.
data/lib/lenna/router.rb DELETED
@@ -1,206 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2023, by Aristóteles Coutinho.
5
-
6
- require 'erb'
7
- require 'json'
8
-
9
- # External dependencies
10
- require 'rack'
11
-
12
- # Internal dependencies
13
- require 'lenna/middleware/app'
14
- require 'lenna/middleware/default/error_handler'
15
- require 'lenna/middleware/default/logging'
16
- require 'lenna/router/builder'
17
- require 'lenna/router/cache'
18
- require 'lenna/router/namespace_stack'
19
- require 'lenna/router/request'
20
- require 'lenna/router/response'
21
- require 'lenna/router/route_matcher'
22
-
23
- module Lenna
24
- # The Node struct is used to represent a node in the tree of routes.
25
- #
26
- # @attr children [Hash] the children of the node
27
- # @attr endpoint [String] the endpoint of the node
28
- # @attr placeholder_name [String] the name of the placeholder
29
- # @attr placeholder [Bool] whether the node is a placeholder
30
- #
31
- Node =
32
- ::Struct.new(:children, :endpoint, :placeholder_name, :placeholder) do
33
- def initialize(children = {}, endpoint = nil, placeholder_name = nil)
34
- super(children, endpoint, placeholder_name, !placeholder_name.nil?)
35
- end
36
- end
37
- public_constant :Node
38
-
39
- # The router class is responsible for adding routes and calling the
40
- # middleware chain for each request.
41
- #
42
- # @private
43
- #
44
- class Router
45
- # @return [Node] the root node of the tree of routes
46
- #
47
- attr_reader :root_node
48
-
49
- # @return [Route::Cache] the cache of routes
50
- #
51
- attr_reader :cache
52
-
53
- # @return [Route::NamespaceStack] the stack of namespaces
54
- #
55
- attr_reader :namespace_stack
56
-
57
- # @return [MiddlewareManager] the middleware manager
58
- #
59
- attr_reader :middleware_manager
60
-
61
- # @return [Route::Builder] the route builder
62
- #
63
- attr_reader :roter_builder
64
-
65
- # This method is used to initialize the router.
66
- # By default, it uses the App middleware and the Cache.
67
- #
68
- # @return [void]
69
- #
70
- def initialize(middleware_manager: Middleware::App.instance, cache: Cache.new)
71
- @cache = cache
72
- @root_node = Node.new({}, nil)
73
- @middleware_manager = middleware_manager
74
- @namespace_stack = NamespaceStack.new
75
- @roter_builder = Builder.new(@root_node)
76
- end
77
-
78
- # This method is used to add a namespace to the routes.
79
- #
80
- # @parameter prefix [String] the prefix to be used
81
- # @parameter block [Proc] the block to be executed
82
- #
83
- # @return [void]
84
- #
85
- # @public `Since v0.1.0`
86
- #
87
- # see {Route::NamespaceStack#push}
88
- #
89
- # ex.
90
- #
91
- # namespace '/api' do |route|
92
- # route.get '/users' do
93
- # # ...
94
- # end
95
- # end
96
- #
97
- def namespace(prefix, &block)
98
- @namespace_stack.push(prefix)
99
- block.call(self)
100
- @namespace_stack.pop
101
- end
102
-
103
- # This method is used to add a middleware to the middleware manager.
104
- #
105
- # See {MiddlewareManager#use}
106
- #
107
- # @public `Since v0.1.0`
108
- #
109
- #
110
- # @parameter middlewares [Array] the middlewares to be used
111
- #
112
- # @return [void]
113
- #
114
- def use(*middlewares) = @middleware_manager.use(middlewares)
115
-
116
- # Proxy methods to add routes
117
- #
118
- # @parameter path [String] the path to be matched
119
- # @parameter * [Array] the middlewares to be used
120
- # @yield { ... } the block to be executed
121
- #
122
- # @return [void]
123
- #
124
- # see {#add_route}
125
- #
126
- # @public `Since v0.1`
127
- def get(path, *, &) = add_route(::Rack::GET, path, *, &)
128
- def put(path, *, &) = add_route(::Rack::PUT, path, *, &)
129
- def post(path, *, &) = add_route(::Rack::POST, path, *, &)
130
- def delete(path, *, &) = add_route(::Rack::DELETE, path, *, &)
131
-
132
- def call(env) = dup.call!(env)
133
-
134
- # This method is used to call the middleware chain for each request.
135
- # It also sets the RACK_ENV to development if it is not set.
136
- #
137
- # @parameter env [Hash] the Rack env
138
- #
139
- # @return [Array] the Lennarb::Response
140
- #
141
- def call!(env)
142
- # TODO: Use pifano to set middlewares by environment.
143
- #
144
- middlewares_by_enviroment =
145
- if ENV['RACK_ENV'] == 'development'
146
- [
147
- Middleware::Default::Logging,
148
- Middleware::Default::ErrorHandler
149
- ]
150
- else
151
- []
152
- end
153
-
154
- middleware_pipeline = @middleware_manager.fetch_or_build_middleware_chain(
155
- method(:process_request),
156
- middlewares_by_enviroment
157
- )
158
-
159
- req = Request.new(env)
160
- res = Response.new
161
-
162
- middleware_pipeline.call(req, res)
163
-
164
- res.finish
165
- end
166
-
167
- private
168
-
169
- # This method is used to add a route to the tree of routes.
170
- #
171
- # @parameter http_method [Rack::Method] the http method to be used
172
- # @parameter path [String] the path to be matched
173
- # @parameter middlewares [Array] the middlewares to be used
174
- # @parameter action [Proc] the action to be executed
175
- #
176
- # see {MiddlewareManager#build_middleware_chain}
177
- # see {Route::Cache#add}
178
- # see {Route::Builder#call}
179
- # see {Route::NamespaceStack#current_prefix}
180
- #
181
- # @return [void]
182
- #
183
- def add_route(http_method, path, *middlewares, &action)
184
- full_path = @namespace_stack.current_prefix + path
185
-
186
- middleware_chain = @middleware_manager.fetch_or_build_middleware_chain(action, middlewares, http_method:, path:)
187
-
188
- @roter_builder.call(http_method, full_path, middleware_chain, @cache)
189
- end
190
-
191
- # This method is used to process the request.
192
- #
193
- # It uses the Route::Matcher to match the request to a route and
194
- # execute the action.
195
- #
196
- # @parameter req [Request] the request
197
- # @parameter res [Response] the response
198
- #
199
- # @return [void]
200
- #
201
- def process_request(req, res)
202
- @route_matcher ||= RouteMatcher.new(@root_node)
203
- @route_matcher.match_and_execute_route(req, res)
204
- end
205
- end
206
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2023, by Aristóteles Coutinho.
5
-
6
- module Lennarb
7
- # The ArrayExtensions module is used to add the wrap method to the Array
8
- # class.
9
- #
10
- # @public Since `v0.1.0`
11
- #
12
- module ArrayExtensions
13
- # Wraps the object in an array if it is not already an array.
14
- #
15
- # @param object [Object] the object to wrap
16
- #
17
- # @return [Array] the wrapped object
18
- #
19
- def wrap(object)
20
- if object.nil?
21
- []
22
- elsif object.respond_to?(:to_ary)
23
- object.to_ary || [object]
24
- else
25
- [object]
26
- end
27
- end
28
- end
29
- end
30
-
31
- Array.extend(Lennarb::ArrayExtensions)