singer 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d324ad6ec097b02fe9db6ab844205b37dd6a53450d69d5c7780d5bd7e7743efa
4
- data.tar.gz: 9990fccac83a6ce04a3d89da50e7dd6b109edbfb74fa48e938b40839c34dfe5e
3
+ metadata.gz: 23ff6172f3189c234f2b95c1aaee2a67e5b91ffd10c88375c54e37cb4417abb5
4
+ data.tar.gz: 037ff1bd0e545efd4156ad9ff84cb2934070f0e704e05156acbff1fd7d787cfb
5
5
  SHA512:
6
- metadata.gz: b5ae6fa28d28668e5afa00615770a6e69628f767e7adaa1344d26bc6e9e0e4c26a60c17aeb51ccae165ad4e50a77fac52b9e38d391d3de01ff398df36bda6682
7
- data.tar.gz: f1f56ff0b4234f45d9a68835d9c69110481567aa7a3554f06240913b6125e9017439d601754e522710b326bf6f402b1771f181b2ffb27cf746da1a8fc3762990
6
+ metadata.gz: 494f03f90b0584d1c0ba3ae4b72454151e8379591082e51fa61cbaae3ad65c50b91463ef52ba56208a7ef6f63d6c8b75f4c4f3c99430a9b367284e337f77cf59
7
+ data.tar.gz: 55646990590d66996705547ed95ff21b21a6a19609db53231c6f416d91fc37d84f0d1fc1c12189b932ade10a479ebef2f619cd5e1a0c8d3b07eb8a1f58f89d4a
@@ -1,4 +1,4 @@
1
1
  module Singer
2
2
  # holds settings
3
- CONFIGURATION = Struct.new(:camelcase_name, :snakecase_name).new
3
+ CONFIGURATION = Struct.new(:template_name, :camelcase_name, :snakecase_name).new
4
4
  end
@@ -18,7 +18,7 @@ module Singer
18
18
  def initialize(path)
19
19
  @path = path
20
20
  Dir.chdir(path) do # we could use only Dir[base: path], but all the code uses relative paths
21
- entries = Dir['**/*']
21
+ entries = Dir.glob('**/*', flags: File::FNM_DOTMATCH)
22
22
  @files = entries.select{ File.file?(_1) }
23
23
  end
24
24
  end
@@ -1,3 +1,3 @@
1
1
  module Singer
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
data/lib/singer.rb CHANGED
@@ -8,11 +8,15 @@ require_relative 'singer/templating_methods'
8
8
  module Singer
9
9
  class Error < StandardError; end
10
10
  class NameMissingError < StandardError; end
11
+ class TemplateUnknown < StandardError; end
12
+
13
+ DEFAULT_TEMPLATE_NAME = 'tdd'.freeze
11
14
 
12
15
  def self.configure(argvies)
13
16
  raise NameMissingError, 'Missing mandatory argument NAME' if argvies.empty?
14
17
 
15
- encase_name(argvies.last)
18
+ encase_name(argvies.pop)
19
+ CONFIGURATION.template_name = argvies.shift || DEFAULT_TEMPLATE_NAME
16
20
  end
17
21
 
18
22
  def self.encase_name(name)
@@ -21,6 +25,10 @@ module Singer
21
25
  end
22
26
 
23
27
  def self.generate
24
- Template.all['tdd'].generate('.')
28
+ unless Template.all.key?(CONFIGURATION.template_name)
29
+ raise TemplateUnknown, "Template #{CONFIGURATION.template_name.inspect} not found"
30
+ end
31
+
32
+ Template.all[CONFIGURATION.template_name].generate('.')
25
33
  end
26
34
  end
@@ -0,0 +1,12 @@
1
+ # Ruby stuff
2
+ /coverage/
3
+ /doc/
4
+ /.bundle/
5
+ /vendor/
6
+
7
+ # prototyping and temporary stuff
8
+ /tmp/
9
+ /todo/
10
+
11
+ # database
12
+ /db/*.sqlite3
@@ -0,0 +1,28 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'colorize'
4
+ gem 'haml'
5
+ gem 'puma'
6
+ gem 'rackup'
7
+ gem 'sassc'
8
+ gem 'sinatra'
9
+ gem 'zeitwerk'
10
+
11
+ group :test do # for humans
12
+ gem 'fivemat'
13
+ gem 'minitest-rg'
14
+ end
15
+
16
+ group :test, :ci do
17
+ gem 'minitest', '~> 5.23.0' # fivemat double-outputs with newer than this
18
+ gem 'mocha'
19
+ gem 'rack-test'
20
+ gem 'rake'
21
+ gem 'rubocop'
22
+ gem 'simplecov'
23
+ end
24
+
25
+ group :ci do # for CI automation
26
+ gem 'minitest-junit'
27
+ gem 'simplecov-cobertura'
28
+ end
@@ -0,0 +1,3 @@
1
+ require_relative '../lib/zeitwerk_setup'
2
+
3
+ run <%= Singer::CONFIGURATION.camelcase_name %>::Server
@@ -0,0 +1,6 @@
1
+ port 80, '0.0.0.0'
2
+
3
+ app_domain = ENV.fetch('APP_DOMAIN', nil)
4
+ cert = "/etc/letsencrypt/live/#{app_domain}/fullchain.pem"
5
+ key = "/etc/letsencrypt/live/#{app_domain}/privkey.pem"
6
+ ssl_bind '0.0.0.0', 443, {cert:, key:} if File.exist?(cert) && File.exist?(key)
@@ -0,0 +1,3 @@
1
+ require 'zeitwerk_setup'
2
+
3
+ <%= Singer::CONFIGURATION.camelcase_name %>::Server.run!
@@ -0,0 +1,8 @@
1
+ module <%= Singer::CONFIGURATION.camelcase_name %>
2
+ # demo class - TODO: remove
3
+ class Hello
4
+ def self.greet(target)
5
+ "Hello, #{target}."
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ require 'sinatra/base'
2
+ require 'haml'
3
+ require 'sassc'
4
+ require 'colorize'
5
+
6
+ module <%= Singer::CONFIGURATION.camelcase_name %>
7
+ # Sinatra app with routes
8
+ class Server < Sinatra::Base
9
+ set :root, '.' # to make directory structure with views/ work
10
+ enable :logging
11
+ configure :development do
12
+ set :bind, '0.0.0.0'
13
+ set :port, 80
14
+ end
15
+
16
+ def dump_errors!(boom, out = @env['rack.errors'])
17
+ filtered_backtrace = boom.backtrace.reject{ _1.include?('/vendor/') }
18
+ header = "#{Time.now.strftime('%F %T')} - #{boom.class} - #{boom.message.white.on_red}:"
19
+ error_message = [header, *filtered_backtrace].join("\n\t")
20
+ out.puts(error_message)
21
+ end
22
+
23
+ def self.compiled_style
24
+ SassC::Engine.new(File.read('views/style.sass'), syntax: :sass).render
25
+ end
26
+ COMPILED_STYLE = compiled_style
27
+
28
+ get '/' do
29
+ redirect '/hello/world'
30
+ end
31
+
32
+ get '/hello/:target' do # TODO: remove
33
+ @salutation = Hello.greet params[:target]
34
+
35
+ haml :index
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,6 @@
1
+ require 'zeitwerk'
2
+
3
+ loader = Zeitwerk::Loader.new
4
+ loader.push_dir 'lib'
5
+ loader.ignore('lib/zeitwerk_setup.rb')
6
+ loader.setup
@@ -0,0 +1,18 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/rg'
3
+
4
+ require 'mocha/minitest'
5
+ Mocha.configure do |c|
6
+ c.display_matching_invocations_on_failure = true
7
+ c.strict_keyword_argument_matching = true
8
+ c.stubbing_method_on_non_mock_object = :allow
9
+ c.stubbing_method_unnecessarily = :prevent
10
+ c.stubbing_non_existent_method = :prevent
11
+ c.stubbing_non_public_method = :allow
12
+ end
13
+
14
+ require 'rack/test'
15
+
16
+ require 'zeitwerk_setup'
17
+
18
+ ENV['APP_ENV'] = 'test' # so that Sinatra and Sequel know we're in test mode
@@ -0,0 +1,32 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestServer < Minitest::Test
4
+ include Rack::Test::Methods
5
+
6
+ def app
7
+ <%= Singer::CONFIGURATION.camelcase_name %>::Server
8
+ end
9
+
10
+ def test_top_level_redirects
11
+ get '/'
12
+
13
+ assert last_response.redirect?
14
+ assert_match %r{/hello/world$}, last_response.headers['location']
15
+ end
16
+
17
+ # TODO: remove
18
+ def test_hello_with_param_slug_includes_a_greeting
19
+ get '/hello/everyone'
20
+
21
+ refute_predicate last_response, :redirect?
22
+ assert_predicate last_response, :ok?
23
+ assert_includes last_response.body, 'Hello, everyone.'
24
+ end
25
+
26
+ def test_hello_without_param_is_a_404_error
27
+ get '/hello'
28
+
29
+ refute_predicate last_response, :ok?
30
+ assert_equal 404, last_response.status
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestServerErrorDumping < Minitest::Test
4
+ def test_dump_errors_backtrace_is_filtered_against_vendor
5
+ exc = generate_exception_with_realistic_backtrace
6
+ assert exc.backtrace.any?{ _1.include?('/vendor/') } # now you see me
7
+
8
+ log = mock()
9
+ log.expects(:puts).with do |message|
10
+ refute message.lines.any?{ _1.include?('/vendor/') } # now you don't
11
+ end
12
+
13
+ app = <%= Singer::CONFIGURATION.camelcase_name %>::Server.new! # .new! returns real instance without Sinatra::Wrapper
14
+ app.dump_errors!(exc, log)
15
+ end
16
+
17
+ def generate_exception_with_realistic_backtrace
18
+ raise 'ciastka'
19
+ rescue RuntimeError => exc
20
+ exc
21
+ end
22
+
23
+ def test_generate_exception_with_realistic_backtrace
24
+ assert_kind_of RuntimeError, generate_exception_with_realistic_backtrace
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestAutoloading < Minitest::Test
4
+ def test_zeitwerk_has_one_loader
5
+ refute_empty Zeitwerk::Registry.loaders
6
+ assert_equal 1, Zeitwerk::Registry.loaders.size
7
+ end
8
+
9
+ # this test is kinda slow, but not as slow as Rack::Test
10
+ def test_zeitwerk_eager_autoloading_works
11
+ loader = Zeitwerk::Registry.loaders.first
12
+ # loader.log!
13
+ loader.eager_load(force: true)
14
+ rescue Zeitwerk::NameError => exc
15
+ flunk exc.message
16
+ else
17
+ pass
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ require 'minitest_helper'
2
+
3
+ # TODO: remove
4
+ class TestHello < Minitest::Test
5
+ def test_greet_with_a_param_generates_a_greeting_string
6
+ assert_equal 'Hello, stranger.', <%= Singer::CONFIGURATION.camelcase_name %>::Hello.greet(:stranger)
7
+ end
8
+ end
@@ -0,0 +1 @@
1
+ #salutation= @salutation
@@ -0,0 +1,7 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title <%= Singer::CONFIGURATION.camelcase_name %>
5
+ %meta{charset: 'UTF-8'}
6
+ %style!= COMPILED_STYLE
7
+ %body!= yield
@@ -0,0 +1,17 @@
1
+ html
2
+ --primary-font: Departure Mono, Joystix Monospace, ui-monospace, monospace, sans-serif
3
+ font-family: var(--primary-font)
4
+ font-size: 64px
5
+ body
6
+ --color-text: Black
7
+ --color-background: White
8
+ color: var(--color-text)
9
+ background-color: var(--color-background)
10
+ margin: 0px
11
+ body > *
12
+ padding: 1em
13
+
14
+ @media (prefers-color-scheme: dark)
15
+ body
16
+ --color-text: White
17
+ --color-background: #222
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # gem 'awesome_print'
4
+ gem 'colorize'
5
+ gem 'minitest'
6
+ gem 'minitest-rg'
7
+ # gem 'rake'
8
+ # gem 'rubocop'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: singer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emil Chludziński
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-21 00:00:00.000000000 Z
10
+ date: 2025-01-26 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: erb
@@ -42,6 +42,23 @@ files:
42
42
  - lib/singer/template.rb
43
43
  - lib/singer/templating_methods.rb
44
44
  - lib/singer/version.rb
45
+ - templates/sinatra_app/.gitignore
46
+ - templates/sinatra_app/Gemfile
47
+ - templates/sinatra_app/config/config.ru
48
+ - templates/sinatra_app/config/puma.rb
49
+ - templates/sinatra_app/exe/server.rb
50
+ - templates/sinatra_app/lib/__SNAKECASE_NAME__/hello.rb
51
+ - templates/sinatra_app/lib/__SNAKECASE_NAME__/server.rb
52
+ - templates/sinatra_app/lib/zeitwerk_setup.rb
53
+ - templates/sinatra_app/test/minitest_helper.rb
54
+ - templates/sinatra_app/test/server/test_server.rb
55
+ - templates/sinatra_app/test/server/test_server_error_dumping.rb
56
+ - templates/sinatra_app/test/test_autoloading.rb
57
+ - templates/sinatra_app/test/test_hello.rb
58
+ - templates/sinatra_app/views/index.haml
59
+ - templates/sinatra_app/views/layout.haml
60
+ - templates/sinatra_app/views/style.sass
61
+ - templates/tdd/Gemfile
45
62
  - templates/tdd/lib/__SNAKECASE_NAME__.rb
46
63
  - templates/tdd/test/test___SNAKECASE_NAME__.rb
47
64
  homepage: https://gitlab.com/tanstaafl/singer/