lennarb 0.1.6 → 0.1.7

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: 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.