lennarb 1.1.0 → 1.3.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/license.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2023-2024, by Aristóteles Coutinho.
4
- Copyright, 2023, by aristotelesbr.
3
+ Copyright (c) 2023-2025 Aristótels Coutinho
5
4
 
6
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
6
  of this software and associated documentation files (the "Software"), to deal
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: 1.1.0
4
+ version: 1.3.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: 2024-10-07 00:00:00.000000000 Z
11
+ date: 2024-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -180,8 +180,9 @@ files:
180
180
  - changelog.md
181
181
  - exe/lenna
182
182
  - lib/lennarb.rb
183
- - lib/lennarb/application/base.rb
184
183
  - lib/lennarb/plugin.rb
184
+ - lib/lennarb/plugins/hooks.rb
185
+ - lib/lennarb/plugins/mount.rb
185
186
  - lib/lennarb/request.rb
186
187
  - lib/lennarb/response.rb
187
188
  - lib/lennarb/route_node.rb
@@ -212,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
213
  - !ruby/object:Gem::Version
213
214
  version: '0'
214
215
  requirements: []
215
- rubygems_version: 3.5.11
216
+ rubygems_version: 3.5.23
216
217
  signing_key:
217
218
  specification_version: 4
218
219
  summary: Lennarb provides a lightweight yet robust solution for web routing in Ruby,
@@ -1,253 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2023-2024, by Aristóteles Coutinho.
5
-
6
- require 'colorize'
7
-
8
- class Lennarb
9
- module Application
10
- class Base
11
- # @attribute [r] _route
12
- # @returns [RouteNode]
13
- #
14
- # @attribute [r] _middlewares
15
- # @returns [Array]
16
- #
17
- # @attribute [r] _global_after_hooks
18
- # @returns [Array]
19
- #
20
- # @attribute [r] _global_before_hooks
21
- # @returns [Array]
22
- #
23
- # @attribute [r] _after_hooks
24
- # @returns [RouteNode]
25
- #
26
- # @attribute [r] _before_hooks
27
- # @returns [RouteNode]
28
- #
29
- attr_accessor :_route, :_global_after_hooks, :_global_before_hooks, :_after_hooks, :_before_hooks
30
-
31
- # Initialize the Application
32
- #
33
- # @returns [Base]
34
- #
35
-
36
- class << self
37
- def inherited(subclass)
38
- subclass.instance_variable_set(:@_route, Lennarb.new)
39
- subclass.instance_variable_set(:@_middlewares, [])
40
- subclass.instance_variable_set(:@_global_after_hooks, [])
41
- subclass.instance_variable_set(:@_global_before_hooks, [])
42
- subclass.instance_variable_set(:@_after_hooks, Lennarb::RouteNode.new)
43
- subclass.instance_variable_set(:@_before_hooks, Lennarb::RouteNode.new)
44
- end
45
-
46
- def get(...) = @_route.get(...)
47
- def put(...) = @_route.put(...)
48
- def post(...) = @_route.post(...)
49
- def head(...) = @_route.head(...)
50
- def match(...) = @_route.match(...)
51
- def patch(...) = @_route.patch(...)
52
- def delete(...) = @_route.delete(...)
53
- def options(...) = @_route.options(...)
54
-
55
- # @returns [Array] middlewares
56
- def middlewares = @_middlewares
57
-
58
- # Use a middleware
59
- #
60
- # @parameter [Object] middleware
61
- # @parameter [Array] args
62
- # @parameter [Block] block
63
- #
64
- # @returns [Array] middlewares
65
- #
66
- def use(middleware, *args, &block)
67
- @_middlewares << [middleware, args, block]
68
- end
69
-
70
- # Add a before hook
71
- #
72
- # @parameter [String] path
73
- # @parameter [Block] block
74
- #
75
- def before(path = nil, &block)
76
- if path
77
- parts = path.split('/').reject(&:empty?)
78
- @_before_hooks.add_route(parts, :before, block)
79
- else
80
- @_global_before_hooks << block
81
- end
82
- end
83
-
84
- # Add a after hook
85
- #
86
- # @parameter [String] path
87
- # @parameter [Block] block
88
- #
89
- def after(path = nil, &block)
90
- if path
91
- parts = path.split('/').reject(&:empty?)
92
- @_after_hooks.add_route(parts, :after, block)
93
- else
94
- @_global_after_hooks << block
95
- end
96
- end
97
-
98
- # Run the Application
99
- #
100
- # @returns [Base] self
101
- #
102
- # When you use this method, the application will be frozen. And you can't add more routes after that.
103
- # This method is used to run the application in a Rack server so, you can use the `rackup` command
104
- # to run the application.
105
- # Ex. rackup -p 3000
106
- # This command will use the following middleware:
107
- # - Rack::ShowExceptions
108
- # - Rack::MethodOverride
109
- # - Rack::Head
110
- # - Rack::ContentLength
111
- #
112
- def run!
113
- stack = Rack::Builder.new
114
-
115
- use Rack::ShowExceptions if test? || development?
116
- use Rack::MethodOverride
117
- use Rack::Head
118
- use Rack::ContentLength
119
-
120
- middlewares.each do |(middleware, args, block)|
121
- stack.use(middleware, *args, &block)
122
- end
123
-
124
- stack.run ->(env) do
125
- catch(:halt) do
126
- execute_hooks(@_before_hooks, env, :before)
127
- res = @_route.call(env)
128
- execute_hooks(@_after_hooks, env, :after)
129
- res
130
- rescue StandardError => e
131
- render_error if production?
132
-
133
- puts e.message.red
134
- puts e.backtrace
135
- raise e
136
- end
137
- end
138
-
139
- @_route.freeze!
140
-
141
- stack.to_app
142
- end
143
-
144
- def test? = ENV['RACK_ENV'] == 'test' || ENV['LENNARB_ENV'] == 'test'
145
- def production? = ENV['RACK_ENV'] == 'production' || ENV['LENNARB_ENV'] == 'production'
146
- def development? = ENV['RACK_ENV'] == 'development' || ENV['LENNARB_ENV'] == 'development'
147
-
148
- # Render a not found
149
- #
150
- # @returns [void]
151
- #
152
- def render_not_found(content = nil)
153
- default = File.exist?('public/404.html')
154
- body = content || default || 'Not Found'
155
- throw :halt, [404, { 'content-type' => 'text/html' }, [body]]
156
- end
157
-
158
- # Render an error
159
- #
160
- # @returns [void]
161
- #
162
- def render_error(content = nil)
163
- default = File.exist?('public/500.html')
164
- body = content || default || 'Internal Server Error'
165
- throw :halt, [500, { 'content-type' => 'text/html' }, [body]]
166
- end
167
-
168
- # Redirect to a path
169
- #
170
- # @parameter [String] path
171
- # @parameter [Integer] status default is 302
172
- #
173
- def redirect(path, status = 302) = throw :halt, [status, { 'location' => path }, []]
174
-
175
- # Include a plugin in the application
176
- #
177
- # @parameter [String] plugin_name
178
- # @parameter [Array] args
179
- # @parameter [Block] block
180
- #
181
- # @returns [void]
182
- #
183
- def plugin(plugin_name, *, &)
184
- @_route.plugin(plugin_name, *, &)
185
- plugin_module = @_route.class::Plugin.load(plugin_name)
186
-
187
- include plugin_module::InstanceMethods if plugin_module.const_defined?(:InstanceMethods)
188
- extend plugin_module::ClassMethods if plugin_module.const_defined?(:ClassMethods)
189
- end
190
-
191
- private
192
-
193
- # Execute the hooks
194
- #
195
- # @parameter [RouteNode] hook_route
196
- # @parameter [Hash] env
197
- # @parameter [Symbol] action
198
- #
199
- # @returns [void]
200
- #
201
- def execute_hooks(hook_route, env, action)
202
- execute_global_hooks(env, action)
203
-
204
- execute_route_hooks(hook_route, env, action)
205
- end
206
-
207
- # Execute the global hooks
208
- #
209
- # @parameter [Hash] env
210
- # @parameter [Symbol] action
211
- #
212
- # @returns [void]
213
- #
214
- def execute_global_hooks(env, action)
215
- global_hooks = action == :before ? @_global_before_hooks : @_global_after_hooks
216
- global_hooks.each { |hook| hook.call(env) }
217
- end
218
-
219
- # Execute the route hooks
220
- #
221
- # @parameter [RouteNode] hook_route
222
- # @parameter [Hash] env
223
- # @parameter [Symbol] action
224
- #
225
- # @returns [void]
226
- #
227
- def execute_route_hooks(hook_route, env, action)
228
- parts = parse_path(env)
229
- return unless parts
230
-
231
- block, = hook_route.match_route(parts, action)
232
- block&.call(env)
233
- end
234
-
235
- # Parse the path
236
- #
237
- # @parameter [Hash] env
238
- #
239
- # @returns [Array] parts
240
- #
241
- def parse_path(env) = env[Rack::PATH_INFO]&.split('/')&.reject(&:empty?)
242
-
243
- # Check if the request is a HTML request
244
- #
245
- # @parameter [Hash] env
246
- #
247
- # @returns [Boolean]
248
- #
249
- def html_request?(env) = env['HTTP_ACCEPT']&.include?('text/html')
250
- end
251
- end
252
- end
253
- end