lennarb 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 133bc5b7fbe787ae7bf9d17f79cddb09d75f3e1d12e99deff891edae698b109a
4
- data.tar.gz: de9d4b466c30c19b1fd84e6d55c162f144904aa09d22d4bc874bb7291eb72ce8
3
+ metadata.gz: b3b1fe759bb5de90ef757201a4023c441a9c40146f31a318aecc5c5c08cd04bb
4
+ data.tar.gz: 8137ee838ca5636d7013cbfa5aa5f7e83d66e3b28d3387255b702d82becd884a
5
5
  SHA512:
6
- metadata.gz: 1aa540d8f1f3d7d82104f441f4d141249485597d34d80072bb2c5df38237ea2651dba35b4f2499f00be7c9d1a94755c2400aefbe102283ff5a0ea3341dc74e97
7
- data.tar.gz: 5660b98b90c019ff4501076845668ddea45210e701d91eae9b99c38a36ee7605511903178e986239934078d22aa8d7156d6efe4c73560e5c4951d7c734fa6f77
6
+ metadata.gz: 3216bc56c89485d3292b621dcdfb26082957bea1ecfc622107b2f631f86508d7eb5318ce5bc43889ccf0db59775dcefd34e7e4ac00f5b023f34c4f371bab83b9
7
+ data.tar.gz: 944b432173eeeee78c2fc8d546ee74f6768ab3581a61babfdad27f8e54969afd96581259d8866126a3e6e26c2418f92355af8cc07d3aa215b0f9fb9a6bceccc0
data/changelog.md CHANGED
@@ -5,6 +5,51 @@ 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.1.7] - 2023-23-12
9
+
10
+ ### Added
11
+
12
+ - Add `console` gem to print the logs in the console.
13
+
14
+ - Add CLI module to:
15
+ - Create a new project with `lennarb new` command.
16
+ - Run the server with `lennarb server` command.
17
+
18
+ - Add simple guide to create and run a project with Lennarb. See [guides/command-line/readme.md](guides/command-line/readme.md) for more details.
19
+
20
+ - Add `Reload` middleware to reload the application in development environment. You can import and use this middleware in your application. Ex.
21
+
22
+ ```rb
23
+ # app.rb
24
+
25
+ require 'lenna/middleware/default/reload'
26
+
27
+ app = Lenna::Application.new
28
+
29
+ app.use Lenna::Middleware::Default::Reload
30
+ ```
31
+
32
+ In the next version, this middleware will be available by default in development environment.
33
+
34
+ - Add `root` method to `Lennarb` module to get the root path of the project. Ex.
35
+
36
+ ```rb
37
+ # app.rb
38
+
39
+ Lennarb.root.join('app.rb')
40
+ # => /home/user/project/app.rb
41
+ ```
42
+
43
+ - Add `zeitwerk` gem to load the files in the project.
44
+
45
+ ### Remove
46
+
47
+ - Remove `Logging` and `ErrorHandling` middlewares from any environment. Now, theses middlewares are only available in development environment.
48
+
49
+ ### Changed
50
+
51
+ - Change log level to `fatal` in test environment.
52
+
8
53
  ## [0.1.6] - 2023-21-12
9
54
 
10
55
  ### Changed
@@ -81,16 +126,16 @@ request.params = { name: 'John' }
81
126
  require 'lennarb'
82
127
 
83
128
  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
129
+ app.get '/hello' do |req, res|
130
+ res.status = 200
131
+ res['Content-Type'] = 'text/plain'
132
+ res.body = 'Hello World'
133
+ end
134
+ app.post '/hello' do |req, res|
135
+ res.status = 200
136
+ res['Content-Type'] = 'text/plain'
137
+ res.body = 'Hello World'
138
+ end
94
139
  end
95
140
 
96
141
  run app
data/exe/lenna ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Released under the MIT License.
5
+ # Copyright, 2023, by Aristóteles Coutinho.
6
+
7
+ # Require the main file
8
+ #
9
+ # @private `Since v0.1`
10
+ #
11
+ require 'lennarb'
12
+
13
+ # Call the CLI to start the server
14
+ #
15
+ # @private `Since v0.1`
16
+ #
17
+ Lenna::Cli::App.run!(ARGV)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ module Lenna
7
+ module Cli
8
+ # Mediator class for CLI
9
+ #
10
+ # @private `Since v0.1.0`
11
+ #
12
+ module App
13
+ extend self
14
+ # Execute the command
15
+ #
16
+ # @return [void]
17
+ #
18
+ def run!(args)
19
+ subcommand = args.shift
20
+
21
+ strategy = parse_options(subcommand, args)
22
+
23
+ strategy.is_a?(Lenna::Cli::Commands::Interface) or fail ::ArgumentError
24
+
25
+ strategy.call
26
+ end
27
+
28
+ private
29
+
30
+ def parse_options(command, args)
31
+ case command
32
+ in 'new' | 'start' then Lenna::Cli::Commands::CreateProject.new(args)
33
+ in 'server' | 's' then Lenna::Cli::Commands::StartServer.new(args)
34
+ else 'help'
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ require 'console'
7
+ require 'erb'
8
+ require 'fileutils'
9
+
10
+ module Lenna
11
+ module Cli
12
+ module Commands
13
+ # Command for creating a new app
14
+ #
15
+ # @private `Since v0.1.0`
16
+ #
17
+ class CreateProject
18
+ include ::Lenna::Cli::Commands::Interface
19
+
20
+ # @!attribute [r] app_name
21
+ #
22
+ private attr_accessor :app_name
23
+
24
+ # Initialize the command
25
+ #
26
+ # @parameter app_name [Array<String>] The name of the app
27
+ #
28
+ def initialize(app_name)
29
+ self.app_name = app_name[0]
30
+ end
31
+
32
+ # Execute the command
33
+ #
34
+ # @parameter app_name [String] The name of the app
35
+ #
36
+ # @return [void]
37
+ #
38
+ def call
39
+ return puts 'Please specify an app name'.red if app_name.nil?
40
+
41
+ create_app(app_name) do
42
+ create_gemfile
43
+ create_config_ru
44
+ create_app_directory
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Create a directory for the app
51
+ #
52
+ # @parameter app_name [String] The name of the app
53
+ #
54
+ # @yield { ... } The block to be executed after the directory
55
+ #
56
+ # @return [void]
57
+ #
58
+ def create_app(app_name)
59
+ ::Console.info("Creating a new app named #{app_name}")
60
+
61
+ ::FileUtils.mkdir_p(app_name)
62
+
63
+ ::FileUtils.cd(app_name).tap { yield app_name } if block_given?
64
+
65
+ app_name
66
+ end
67
+
68
+ # Create a new Gemfile for the app. This will be use template
69
+ # file in the `templates` directory.
70
+ #
71
+ # @parameter app_name [String] The name of the app
72
+ #
73
+ # @return [void]
74
+ #
75
+ def create_gemfile
76
+ { version: Lennarb::VERSION }.then { create_template('gemfile', _1, 'Gemfile') }
77
+ end
78
+
79
+ # Create a new config.ru for the app. This will be use template
80
+ # file in the `templates` directory.
81
+ #
82
+ # @return [void]
83
+ #
84
+ def create_config_ru
85
+ create_template('config.ru', {})
86
+ end
87
+
88
+ # Create a new application.rb for the app. This will be use template
89
+ # file in the `templates` directory.
90
+ #
91
+ # @return [void]
92
+ #
93
+ # @See #create_template
94
+ # @See lenna/cli/templates/application
95
+ #
96
+ def create_app_directory
97
+ simple_template = <<~HTML.strip
98
+ '<h2>Hello, welcome to Lenna! #{Lennarb::VERSION}</h1>'
99
+ HTML
100
+ create_template('application', { simple_template: }, 'app/application.rb')
101
+ end
102
+
103
+ # Method for creating file based on a template
104
+ #
105
+ # @parameter template_name [String] The name of the template
106
+ # @parameter template_data [Hash] The data to be used in the template
107
+ #
108
+ # @return [void]
109
+ #
110
+ def create_template(template_name, template_data, file_name = template_name)
111
+ Lennarb # rubocop:disable Lint
112
+ .root
113
+ .join("lib/lenna/cli/templates/#{template_name}.erb")
114
+ .then { ::File.read(_1) }
115
+ .then { ::ERB.new(_1).result_with_hash(template_data) }
116
+ .then do |content|
117
+ return ::File.write(file_name, content) unless file_name.include?('/')
118
+
119
+ ::FileUtils.mkdir_p(::File.dirname(file_name)) && ::File.write(file_name, content)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ module Lenna
7
+ module Cli
8
+ module Commands
9
+ module Interface
10
+ def new(args)
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def call
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ require 'console'
7
+ require 'optparse'
8
+
9
+ module Lenna
10
+ module Cli
11
+ module Commands
12
+ # Command for creating a new app
13
+ #
14
+ # @private `Since v0.1.0`
15
+ #
16
+ class StartServer
17
+ include Lenna::Cli::Commands::Interface
18
+
19
+ # @!attribute [rw] port
20
+ # @return [Integer] Port to start the server
21
+ #
22
+ private attr_accessor :port
23
+ # @!attribute [rw] server
24
+ # @return [String] Server to start
25
+ #
26
+ private attr_accessor :server
27
+ # @!attribute [rw] command
28
+ # @return [String] Command to execute
29
+ #
30
+ private attr_accessor :command
31
+
32
+ def initialize(args)
33
+ self.command = args.shift
34
+
35
+ options = parse_options!(args)
36
+
37
+ self.port = options[:port]
38
+ self.server = options[:server]
39
+ end
40
+
41
+ # Execute the command
42
+ #
43
+ # @return [void]
44
+ #
45
+ def call
46
+ ::Console.debug("Starting server on port #{port}...")
47
+
48
+ case server
49
+ in 'puma' | 'falcon' => server then start_server(port:, server:)
50
+ else fail ::ArgumentError, ::Console.error("The server '#{server}' is not supported yet.")
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # Parse the options
57
+ #
58
+ # @parameter args [Array<String>] The arguments
59
+ #
60
+ # @return [Hash] The options
61
+ #
62
+ def parse_options!(args)
63
+ options = { port: 4000, server: 'puma' }
64
+
65
+ ::OptionParser.new do |opts|
66
+ opts.banner = "Usage: lenna #{command} [options]"
67
+
68
+ opts.on('-p', '--port [PORT]', Integer, 'Port to start the server') do |port|
69
+ options[:port] = port
70
+ end
71
+
72
+ opts.on('-s', '--server [SERVER]', String, 'Server to start') do |server|
73
+ options[:server] = server
74
+ end
75
+ end.parse!(args)
76
+
77
+ options
78
+ end
79
+
80
+ # Start the server
81
+ #
82
+ # @paramaeter port [Integer] Port to start the server
83
+ # @paramaeter server [String] Server to start
84
+ #
85
+ # @return [void]
86
+ #
87
+ def start_server(port:, server:)
88
+ return warn_not_installed(server) unless instaled_gem?(server)
89
+
90
+ ::File.exist?(config_file) or fail ::StandardError, ::Console.error("'config.ru' not found in #{poroject_name}.")
91
+
92
+ system("bundle exec #{server} #{config_file} --port #{port}", chdir: current_path)
93
+ rescue ::ArgumentError
94
+ ::Console.error("The server '#{server}' is not supported yet.")
95
+ rescue ::Interrupt
96
+ ::Console.info("\nServer stopped.")
97
+ rescue ::StandardError => e
98
+ ::Console.error(self, e.message)
99
+ end
100
+
101
+ # Check if the gem is installed
102
+ #
103
+ # @parameter name [String] Name of the gem
104
+ #
105
+ # @return [Boolean]
106
+ #
107
+ def instaled_gem?(name)
108
+ ::Gem::Specification.find_by_name(name)
109
+ rescue ::Gem::LoadError
110
+ false
111
+ end
112
+
113
+ # Get the name of the project
114
+ #
115
+ # @return [String] Name of the project
116
+ #
117
+ def poroject_name = @current_path.split('/').last
118
+
119
+ # Get the path of the project
120
+ #
121
+ # @return [String] Path of the project
122
+ #
123
+ def current_path = @current_path ||= ::Dir.pwd
124
+
125
+ # Get the path of the config file
126
+ #
127
+ # @return [String] Path of the config file
128
+ #
129
+ def config_file = "#{current_path}/config.ru"
130
+
131
+ # Warn the user that the gem is not installed
132
+ #
133
+ # @parameter name [String] Name of the gem
134
+ #
135
+ # @return [void]
136
+ #
137
+ def warn_not_installed(name)
138
+ ::Console.warn("The gem '#{name}' is not installed. Please install it and try again.")
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lennarb'
4
+
5
+ class Application
6
+ include Lenna::Base
7
+
8
+ app.get '/' do |req, res|
9
+ res.html(<%= simple_template %>)
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'app/application'
4
+
5
+ run Application.app
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # [https://rubygems.org/gems/lennarb]
6
+ # Lenna is a lightweight and experimental web framework for Ruby. It's designed
7
+ # to be modular and easy to use. Also, that's how I affectionately call my wife.
8
+ gem 'lennarb', '~> <%= version %>'
9
+ # [https://rubygems.org/gems/puma]
10
+ # Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for Ruby/Rack applications.
11
+ gem 'puma', '~> 6.4'
12
+
13
+ group :development, :test do
14
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
6
+ require 'console'
7
+
8
+ # This middleware is used to reload files in development mode.
9
+ #
10
+ module Lenna
11
+ module Middleware
12
+ module Default
13
+ class Reload
14
+ attr_accessor :directories, :files_mtime
15
+
16
+ # Initializes a new instance of Middleware::Default::Reload.
17
+ #
18
+ # @parameter directories [Array] An array of directories to monitor.
19
+ #
20
+ # @return [Middleware::Default::Reload] A new instance of Middleware::Default::Reload.
21
+ def initialize(directories = [])
22
+ self.files_mtime = {}
23
+ self.directories = directories
24
+
25
+ monitor_directories(directories)
26
+ end
27
+
28
+ # Calls the middleware.
29
+ #
30
+ # @parameter req [Rack::Request] The request.
31
+ # @parameter _res [Rack::Response] The response.
32
+ # @parameter next_middleware [Proc] The next middleware.
33
+ #
34
+ # @return [void]
35
+ #
36
+ def call(_req, _res, next_middleware)
37
+ reload_if_needed
38
+
39
+ next_middleware.call
40
+ rescue ::StandardError => error
41
+ ::Console.error(self, error)
42
+ end
43
+
44
+ private
45
+
46
+ # Reloads files if needed.
47
+ #
48
+ # @return [void]
49
+ #
50
+ def reload_if_needed
51
+ modified_files = check_for_modified_files
52
+
53
+ reload_files(modified_files) unless modified_files.empty?
54
+ end
55
+
56
+ # Monitors directories for changes.
57
+ #
58
+ # @parameter directories [Array] An array of directories to monitor.
59
+ #
60
+ # @return [void]
61
+ #
62
+ def monitor_directories(directories)
63
+ directories.each do |directory|
64
+ ::Dir.glob(directory).each { |file| files_mtime[file] = ::File.mtime(file) }
65
+ end
66
+ end
67
+
68
+ # Checks for modified files.
69
+ #
70
+ # @return [Array] An array of modified files.
71
+ #
72
+ # @example
73
+ # check_for_modified_files #=> ["/path/to/file.rb"]
74
+ #
75
+ def check_for_modified_files
76
+ @files_mtime.select do |file, last_mtime|
77
+ ::File.mtime(file) > last_mtime
78
+ end.keys
79
+ end
80
+
81
+ # Reloads files.
82
+ #
83
+ # @parameter files [Array] An array of files(paths) to reload.
84
+ #
85
+ # @return [void]
86
+ #
87
+ def reload_files(files)
88
+ files.each do |file|
89
+ ::Console.debug("Reloading #{file}")
90
+ ::Kernel.load file
91
+ @files_mtime[file] = ::File.mtime(file)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
data/lib/lenna/router.rb CHANGED
@@ -67,10 +67,7 @@ module Lenna
67
67
  #
68
68
  # @return [void]
69
69
  #
70
- def initialize(
71
- middleware_manager: Middleware::App.instance,
72
- cache: Cache.new
73
- )
70
+ def initialize(middleware_manager: Middleware::App.instance, cache: Cache.new)
74
71
  @cache = cache
75
72
  @root_node = Node.new({}, nil)
76
73
  @middleware_manager = middleware_manager
@@ -142,12 +139,21 @@ module Lenna
142
139
  # @return [Array] the Lennarb::Response
143
140
  #
144
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
+
145
154
  middleware_pipeline = @middleware_manager.fetch_or_build_middleware_chain(
146
155
  method(:process_request),
147
- [
148
- Middleware::Default::Logging,
149
- Middleware::Default::ErrorHandler
150
- ]
156
+ middlewares_by_enviroment
151
157
  )
152
158
 
153
159
  req = Request.new(env)
@@ -177,12 +183,7 @@ module Lenna
177
183
  def add_route(http_method, path, *middlewares, &action)
178
184
  full_path = @namespace_stack.current_prefix + path
179
185
 
180
- middleware_chain = @middleware_manager.fetch_or_build_middleware_chain(
181
- action,
182
- middlewares,
183
- http_method:,
184
- path:
185
- )
186
+ middleware_chain = @middleware_manager.fetch_or_build_middleware_chain(action, middlewares, http_method:, path:)
186
187
 
187
188
  @roter_builder.call(http_method, full_path, middleware_chain, @cache)
188
189
  end
@@ -4,7 +4,7 @@
4
4
  # Copyright, 2023, by Aristóteles Coutinho.
5
5
 
6
6
  module Lennarb
7
- VERSION = '0.1.6'
7
+ VERSION = '0.1.7'
8
8
 
9
9
  public_constant :VERSION
10
10
  end
data/lib/lennarb.rb CHANGED
@@ -13,3 +13,34 @@ require 'lennarb/array_extensions'
13
13
  #
14
14
  require 'lenna/application'
15
15
  require 'lennarb/version'
16
+
17
+ # Core extensions
18
+ #
19
+ require 'pathname'
20
+
21
+ # Zeitwerk
22
+ #
23
+ require 'zeitwerk'
24
+
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
32
+
33
+ # Lennarb module
34
+ #
35
+ module Lennarb
36
+ module_function
37
+
38
+ # Lennarb root path
39
+ #
40
+ # @return [Pathname] the root path
41
+ #
42
+ def root
43
+ File.expand_path('..', __dir__)
44
+ Pathname.new(File.expand_path('..', __dir__))
45
+ end
46
+ end
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.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aristóteles Coutinho
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-21 00:00:00.000000000 Z
11
+ date: 2023-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -24,6 +24,20 @@ 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'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rack
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -44,10 +58,33 @@ dependencies:
44
58
  - - ">="
45
59
  - !ruby/object:Gem::Version
46
60
  version: 3.0.8
61
+ - !ruby/object:Gem::Dependency
62
+ name: zeitwerk
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.6'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.6.12
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '2.6'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.6.12
47
81
  - !ruby/object:Gem::Dependency
48
82
  name: bake
49
83
  requirement: !ruby/object:Gem::Requirement
50
84
  requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '0.18'
51
88
  - - ">="
52
89
  - !ruby/object:Gem::Version
53
90
  version: 0.18.2
@@ -55,6 +92,9 @@ dependencies:
55
92
  prerelease: false
56
93
  version_requirements: !ruby/object:Gem::Requirement
57
94
  requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.18'
58
98
  - - ">="
59
99
  - !ruby/object:Gem::Version
60
100
  version: 0.18.2
@@ -130,15 +170,25 @@ dependencies:
130
170
  version: 0.33.0
131
171
  description:
132
172
  email:
133
- executables: []
173
+ executables:
174
+ - lenna
134
175
  extensions: []
135
176
  extra_rdoc_files: []
136
177
  files:
137
178
  - changelog.md
179
+ - exe/lenna
138
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
139
188
  - lib/lenna/middleware/app.rb
140
189
  - lib/lenna/middleware/default/error_handler.rb
141
190
  - lib/lenna/middleware/default/logging.rb
191
+ - lib/lenna/middleware/default/reload.rb
142
192
  - lib/lenna/router.rb
143
193
  - lib/lenna/router/builder.rb
144
194
  - lib/lenna/router/cache.rb
@@ -175,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
225
  - !ruby/object:Gem::Version
176
226
  version: '0'
177
227
  requirements: []
178
- rubygems_version: 3.5.1
228
+ rubygems_version: 3.4.10
179
229
  signing_key:
180
230
  specification_version: 4
181
231
  summary: A lightweight and experimental web framework for Ruby.