Skip to content

Commit

Permalink
Merge pull request #18 from aristotelesbr/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
aristotelesbr authored Dec 23, 2023
2 parents 5b611b7 + fded78b commit 5ed806b
Show file tree
Hide file tree
Showing 15 changed files with 445 additions and 5 deletions.
17 changes: 16 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ AllCops:
Exclude:
- "bin/**/*"

Naming/RescuedExceptionsVariableName:
Enabled: false

Layout/LineLength:
Max: 80
Max: 120

Layout/IndentationStyle:
EnforcedStyle: tabs
Expand All @@ -31,6 +34,9 @@ Layout/SpaceInLambdaLiteral:
Metrics/BlockLength:
Enabled: false

Lint/RedundantCopDisableDirective:
Enabled: false

Lint/AmbiguousBlockAssociation:
Enabled: false

Expand All @@ -56,6 +62,15 @@ Metrics/ModuleLength:
Metrics/PerceivedComplexity:
Max: 10

Style/MixinGrouping:
Enabled: false

Style/MethodCalledOnDoEndBlock:
Enabled: false

Style/SignalException:
Enabled: false

Style/AsciiComments:
Enabled: false

Expand Down
44 changes: 44 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,50 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.7] - 2023-23-12

## Added

- Add `console` gem to print the logs in the console.
- Add CLI module to run the server. Now, you can run the server with:

```sh
bundle exec lennarb server
```

- Add `--port` option to CLI module. Now, you can run the server in a specific port with:

```sh
bundle exec lennarb server --port 3000
```

- Add `Reload` middleware to reload the application in development environment. You can import and use this middleware in your application. Ex.

```rb
# app.rb

require 'lenna/middleware/default/reload'

app = Lenna::Application.new

app.use Lenna::Middleware::Default::Reload
```

In the next version, this middleware will be available by default in development environment.

- Add `root` method to `Lennarb` module to get the root path of the project. Ex.

```rb
# app.rb

Lennarb.root.join('app.rb')
# => /home/user/project/app.rb
```

## Remove

- Remove `Logging` and `ErrorHandling` middlewares from any environment. Now, theses middlewares are only available in development environment.

## [0.1.6] - 2023-21-12

### Changed
Expand Down
7 changes: 5 additions & 2 deletions gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
# [https://rubygems.org/gems/colorize]
# Colorize is a Ruby gem used to color text in terminals.
gem 'colorize', '~> 1.1'
# [https://rubygems.org/gems/console]
# Console is a Ruby gem used to create interactive command line applications.
gem 'console', '~> 1.23'

group :maintenance, optional: true do
# [https://rubygems.org/gems/bake-gem]
Expand Down Expand Up @@ -44,10 +47,10 @@
# [https://rubygems.org/gems/bake]
# Bake is a build tool for Ruby projects. It is designed to be simple,
# fast and extensible.
gem 'bake'
# [https://rubygems.org/gems/puma]
gem 'bake', '~> 0.18.2'
# Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
# Ruby/Rack applications.
# Ruby/Rack applications.
gem 'puma', '~> 6.4'
# RuboCop is a Ruby code style checking and code formatting tool. It aims to
# enforce the community-driven Ruby Style Guide.
Expand Down
5 changes: 4 additions & 1 deletion lennarb.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ Gem::Specification.new do |spec|
'source_code_uri' => 'https://github.com/aristotelesbr/lennarb'
}

spec.executables = ['lenna']

spec.files = Dir['{lib}/**/*', '*.md', base: __dir__]

spec.required_ruby_version = '>= 3.0'

spec.add_dependency 'colorize', '~> 1.1'
spec.add_dependency 'console', '~> 1.23'
spec.add_dependency 'rack', '~> 3.0', '>= 3.0.8'

spec.add_development_dependency 'bake', '>= 0.18.2'
spec.add_development_dependency 'bake', '~> 0.18', '>= 0.18.2'
spec.add_development_dependency 'covered', '~> 0.25.1'
spec.add_development_dependency 'puma', '~> 6.4'
spec.add_development_dependency 'rack-test', '~> 2.1'
Expand Down
71 changes: 71 additions & 0 deletions lib/lenna/cli/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2023, by Aristóteles Coutinho.

require 'optparse'

require 'lennarb/version'

module Lenna
module Cli
# Mediator class for CLI
#
# @private `Since v0.1.0`
#
class App
# @return [Array] Arguments passed to CLI
#
attr_reader :args

# Initialize a new instance of the class
#
# @parameter args [Array] Arguments passed to CLI
#
def initialize(args)
@args = args
end

# Execute the command
#
# @return [void]
#
def execute(strategy)
strategy.is_a?(Commands::Interface) or fail ::ArgumentError

parser!(@args).then { strategy.execute(_1) }
end

private

# Parse the options passed to CLI
#
# @parameter args [Array] Arguments passed to CLI
#
# @return [Hash] Options passed to CLI
#
def parser!(args)
options = {}
OptionParser.new do |opts|
opts.banner = 'Usage: lenna [options]'

opts.on('-v', '--version', 'Print version') do
puts Lenna::VERSION
exit
end

opts.on('-h', '--help', 'Print help') do
puts opts
exit
end

opts.on('-n', '--new', 'Create a new app') do
options[:new] = true
end
end.parser!(args)

options
end
end
end
end
64 changes: 64 additions & 0 deletions lib/lenna/cli/commands/create_project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

require 'colorize'
require 'erb'
require 'fileutils'
require 'lenna/cli/commands/interface'
require 'lennarb/version'

module Lenna
module Cli
module Commands
# Command for creating a new app
#
# @private `Since v0.1.0`
#
module CreateProject
extend Lenna::Cli::Commands::Interface, self
# Execute the command
#
# @parameter app_name [String] The name of the app
#
# @return [void]
#
def execute(app_name)
return puts 'Please specify an app name' if app_name.nil?

puts "Creating a new app named #{app_name}".green
create_app(app_name)
create_gemfile(app_name)
end

private

# Create a directory for the app
#
# @parameter app_name [String] The name of the app
#
# @return [void]
#
def create_app(app_name) = FileUtils.mkdir_p(app_name)

# Create a new Gemfile for the app. This will be use template
# file in the `templates` directory.
#
# @parameter app_name [String] The name of the app
#
# @return [void]
#
def create_gemfile(app_name)
FileUtils.cd(app_name).tap do
template_data = { version: Lennarb::VERSION }

erb_template =
Lennarb.root.join('lib/lenna/cli/templates/gemfile.erb')
.then { File.read(_1) }
.then { ERB.new(_1) }

File.write('Gemfile', erb_template.result_with_hash(template_data))
end
end
end
end
end
end
13 changes: 13 additions & 0 deletions lib/lenna/cli/commands/interface.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Lenna
module Cli
module Commands
module Interface
def self.execute(args)
raise NotImplementedError
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/lenna/cli/templates/gemfile.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

source 'https://rubygems.org'

# [https://rubygems.org/gems/lennarb]
# Lenna is a lightweight and experimental web framework for Ruby. It's designed
# to be modular and easy to use. Also, that's how I affectionately call my wife.
gem 'lennarb', '~> <%= version %>'
# [https://rubygems.org/gems/falcon]
# A fast, asynchronous, rack-compatible web server.
gem 'falcon', '~> 0.42.3'

group :development, :test do
end
97 changes: 97 additions & 0 deletions lib/lenna/middleware/default/reload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2023, by Aristóteles Coutinho.

require 'console'

# This middleware is used to reload files in development mode.
#
module Lenna
module Middleware
module Default
class Reload
attr_accessor :directories, :files_mtime

# Initializes a new instance of Middleware::Default::Reload.
#
# @parameter directories [Array] An array of directories to monitor.
#
# @return [Middleware::Default::Reload] A new instance of Middleware::Default::Reload.
def initialize(directories = [])
self.files_mtime = {}
self.directories = directories

monitor_directories(directories)
end

# Calls the middleware.
#
# @parameter req [Rack::Request] The request.
# @parameter _res [Rack::Response] The response.
# @parameter next_middleware [Proc] The next middleware.
#
# @return [void]
#
def call(_req, _res, next_middleware)
reload_if_needed

next_middleware.call
rescue ::StandardError => error
::Console.error(self, error)
end

private

# Reloads files if needed.
#
# @return [void]
#
def reload_if_needed
modified_files = check_for_modified_files

reload_files(modified_files) unless modified_files.empty?
end

# Monitors directories for changes.
#
# @parameter directories [Array] An array of directories to monitor.
#
# @return [void]
#
def monitor_directories(directories)
directories.each do |directory|
::Dir.glob(directory).each { |file| files_mtime[file] = ::File.mtime(file) }
end
end

# Checks for modified files.
#
# @return [Array] An array of modified files.
#
# @example
# check_for_modified_files #=> ["/path/to/file.rb"]
#
def check_for_modified_files
@files_mtime.select do |file, last_mtime|
::File.mtime(file) > last_mtime
end.keys
end

# Reloads files.
#
# @parameter files [Array] An array of files(paths) to reload.
#
# @return [void]
#
def reload_files(files)
files.each do |file|
::Console.debug("Reloading #{file}")
::Kernel.load file
@files_mtime[file] = ::File.mtime(file)
end
end
end
end
end
end
Loading

0 comments on commit 5ed806b

Please sign in to comment.