lennarb 0.1.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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)