roda-project 0.1.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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/bin/console +11 -0
  3. data/bin/roda-project +6 -0
  4. data/bin/roda-project.rb +9 -0
  5. data/bin/setup +8 -0
  6. data/lib/roda/project/cli.rb +134 -0
  7. data/lib/roda/project/context.rb +136 -0
  8. data/lib/roda/project/helpers/ids.rb +15 -0
  9. data/lib/roda/project/helpers/input.rb +20 -0
  10. data/lib/roda/project/helpers/template.rb +37 -0
  11. data/lib/roda/project/version.rb +7 -0
  12. data/lib/roda/project.rb +54 -0
  13. data/lib/roda/templates/base/app/app.rb.erb +87 -0
  14. data/lib/roda/templates/base/scaffold/AGENTS.md +9 -0
  15. data/lib/roda/templates/base/scaffold/Gemfile.erb +51 -0
  16. data/lib/roda/templates/base/scaffold/Guardfile +25 -0
  17. data/lib/roda/templates/base/scaffold/README.md +29 -0
  18. data/lib/roda/templates/base/scaffold/Rakefile.erb +209 -0
  19. data/lib/roda/templates/base/scaffold/app/config/config.rb.erb +25 -0
  20. data/lib/roda/templates/base/scaffold/app/config/locales/en.yml +273 -0
  21. data/lib/roda/templates/base/scaffold/app/config/locales/foo/en.yml +2 -0
  22. data/lib/roda/templates/base/scaffold/app/config/locales/foo/pt-br.yml +2 -0
  23. data/lib/roda/templates/base/scaffold/app/config/locales/pt-br.yml +244 -0
  24. data/lib/roda/templates/base/scaffold/app/config/providers/logger.rb +9 -0
  25. data/lib/roda/templates/base/scaffold/app/config/providers/mailer.rb +11 -0
  26. data/lib/roda/templates/base/scaffold/app/routes/foo.rb.erb +7 -0
  27. data/lib/roda/templates/base/scaffold/boot.rb.erb +35 -0
  28. data/lib/roda/templates/base/scaffold/config.ru.erb +13 -0
  29. data/lib/roda/templates/base/scaffold/public/css/app.css +1 -0
  30. data/lib/roda/templates/base/scaffold/public/exception_page.css +16 -0
  31. data/lib/roda/templates/base/scaffold/public/images/roda-project.png +0 -0
  32. data/lib/roda/templates/base/scaffold/public/js/app.js +27 -0
  33. data/lib/roda/templates/database/app/config/providers/db/conn.rb +15 -0
  34. data/lib/roda/templates/database/db/seeds.rb +1 -0
  35. data/lib/roda/templates/front-end/app/assets/css/app.css +20 -0
  36. data/lib/roda/templates/front-end/app/assets/js/app.js +7 -0
  37. data/lib/roda/templates/front-end/app/assets/js/some/foo.js +5 -0
  38. data/lib/roda/templates/front-end/app/views/foo/bar.erb +1 -0
  39. data/lib/roda/templates/front-end/app/views/foo/html.rb +6 -0
  40. data/lib/roda/templates/front-end/app/views/html.rb +22 -0
  41. data/lib/roda/templates/front-end/app/views/index.erb +1 -0
  42. data/lib/roda/templates/front-end/app/views/layout.erb +13 -0
  43. data/lib/roda/templates/front-end/esbuild.js +39 -0
  44. data/lib/roda/templates/front-end/package.json +20 -0
  45. data/lib/roda/templates/rodauth/app/models/account.rb +2 -0
  46. data/lib/roda/templates/rodauth/app/views/create-account.erb +9 -0
  47. data/lib/roda/templates/rodauth/db/migrations/001_add_rodauth.rb +71 -0
  48. data/lib/roda/templates/tests/minitest/spec/app/app_spec.rb.erb +15 -0
  49. data/lib/roda/templates/tests/minitest/spec/app/routes/foo_spec.rb +8 -0
  50. data/lib/roda/templates/tests/minitest/spec/app/routes/test_branch_spec.rb +4 -0
  51. data/lib/roda/templates/tests/minitest/spec/app/views/html_spec.rb +0 -0
  52. data/lib/roda/templates/tests/minitest/spec/spec_helper.rb.erb +33 -0
  53. data/lib/roda/templates/tests/rspec/spec/app/app_spec.rb.erb +15 -0
  54. data/lib/roda/templates/tests/rspec/spec/app/routes/foo_spec.rb +8 -0
  55. data/lib/roda/templates/tests/rspec/spec/app/routes/test_branch_spec.rb +4 -0
  56. data/lib/roda/templates/tests/rspec/spec/app/views/html_spec.rb +0 -0
  57. data/lib/roda/templates/tests/rspec/spec/spec_helper.rb.erb +19 -0
  58. metadata +142 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9ee06fbd7dc545302e76dae3d4a7b6bf1dfbc96bcd93069192898ae42260cc69
4
+ data.tar.gz: 6b25df32eeac0001a9aecf1bacf15b47b100e03a5d7ce48066b0d50e0c2e1e3a
5
+ SHA512:
6
+ metadata.gz: 626e1417abaad740b5e687ebb46179a1cb72c83d70e3388251cf80d48a0003fc758a0ced41089ea7f44adf9e79a15410ed61ec4222c7b38cd0f4029a12cfc638
7
+ data.tar.gz: f6746dde88bb1896bf238d0d250b9c2b1fd368f35b9bab7be3c9f74fee14e35fc1152f24f43e3ea58912ed27543b9d77036d586fd8d9d2209a4fbf0183cc592a
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "roda/project"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ require "irb"
11
+ IRB.start(__FILE__)
data/bin/roda-project ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'roda/project'
5
+
6
+ Roda::Project::CLI.new.call
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/roda/project'
5
+
6
+ Roda::Project::CLI.new.call
7
+
8
+
9
+
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roda
4
+ module Project
5
+ class CLI
6
+ include Helpers::Template
7
+ include Helpers::Input
8
+ include Helpers::Ids
9
+
10
+ def initialize(context: Context.new, pastel: Pastel.new, dir: nil)
11
+ @context = context
12
+ @pastel = pastel
13
+ @dir = dir
14
+ end
15
+
16
+ def call
17
+ puts @pastel.bright_black("[roda-project v#{Roda::Project::VERSION}]\n")
18
+ puts @pastel.italic("#{Roda::Project.messages.sample.first}\n")
19
+
20
+ get_user_context
21
+
22
+ puts @pastel.bright_black("\n[project: #{@context.project_name}]\n")
23
+
24
+ create_base_project
25
+ add_front_end
26
+ add_database
27
+ add_test_files
28
+
29
+ puts "\ninstall dependences:\n\n"
30
+ puts "$ cd #{@context.project_name} && bundle"
31
+ if @context.database?
32
+ unless @context.sqlite?
33
+ puts "\n* create your database\n"
34
+ puts "\n* put your dev database credentials in app/config/config.rb\n"
35
+ end
36
+ puts "\nmigrate the database (use RACK_ENV to migrate 'test' or 'production' environments):\n\n"
37
+ puts "$ rake db:migrate"
38
+ end
39
+ puts "\nrun and watch the project in dev mode:\n"
40
+ puts "\n$ rake dev:watch"
41
+ if @context.fullstack?
42
+ puts "\ncompile and watch assets:\n"
43
+ puts "\n$ rake assets:watch"
44
+ end
45
+ puts "\nrun 'rake' inside #{@context.project_name} to see all available tasks\n\n"
46
+ rescue TTY::Reader::InputInterrupt
47
+ puts "\n\nGoodbye"
48
+ end
49
+
50
+ private
51
+
52
+ def get_user_context
53
+ retry_on_error { @context.project_name = read_line("Project name › ", "project") }
54
+ retry_on_error { @context.base = read_line("(#{fullstack_id}) Fullstack (#{api_id}) API › ", fullstack_id).to_i }
55
+ retry_on_error { @context.tests = read_line("(#{rspec_id}) RSpec (#{minitest_id}) Minitest › ", rspec_id).to_i }
56
+ retry_on_error { @context.database = read_line("Database? (Y/n) › ", true) }
57
+
58
+ if @context.database?
59
+ retry_on_error {
60
+ @context.database_type = read_line(
61
+ "(#{sqlite_id}) SQlite (#{postgresql_id}) PostgreSQL (#{mysql_id}) MySQL › ",
62
+ sqlite_id
63
+ ).to_i
64
+ }
65
+
66
+ retry_on_error { @context.rodauth = read_line("Rodauth? (authentication) (Y/n) › ", true) }
67
+ end
68
+ end
69
+
70
+ def retry_on_error
71
+ yield
72
+ rescue Roda::Project::Context::InvalidValue => e
73
+ puts "\n #{@pastel.red(e.message)} \n\n"
74
+
75
+ yield
76
+ end
77
+
78
+ def create_base_project
79
+ puts "* creating base project"
80
+ TTY::File.copy_directory(
81
+ File.expand_path("../templates/base/scaffold", __dir__),
82
+ "#{@dir}#{@context.project_name}",
83
+ context: @context
84
+ )
85
+
86
+ TTY::File.copy_file(
87
+ File.expand_path("../templates/base/app/app.rb.erb", __dir__),
88
+ "#{@dir}#{@context.project_name}/app/#{@context.project_name}.rb",
89
+ context: @context
90
+ )
91
+ end
92
+
93
+ def add_front_end
94
+ if @context.fullstack?
95
+ puts "* adding front-end"
96
+ tty_cp_r("front-end", "app/assets")
97
+ tty_cp("front-end", "esbuild.js")
98
+ tty_cp("front-end", "package.json")
99
+ cp_r("front-end", "app/views")
100
+ end
101
+ end
102
+
103
+ def add_database
104
+ if @context.database?
105
+ puts "* adding database"
106
+ tty_cp_r("database", "db")
107
+ tty_cp("database", "app/config/providers/db/conn.rb")
108
+ add_rodauth
109
+ end
110
+ end
111
+
112
+ def add_rodauth
113
+ if @context.rodauth?
114
+ puts "* adding rodauth"
115
+ tty_cp_r("rodauth", "app/models")
116
+ tty_cp("rodauth", "db/migrations/001_add_rodauth.rb")
117
+ if @context.fullstack?
118
+ cp("rodauth", "app/views/create-account.erb")
119
+ end
120
+ end
121
+ end
122
+
123
+ def add_test_files
124
+ puts "* adding test files"
125
+
126
+ if @context.rspec?
127
+ tty_cp_r("tests/rspec", "spec")
128
+ else
129
+ tty_cp_r("tests/minitest", "spec")
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,136 @@
1
+ module Roda
2
+ module Project
3
+ class Context
4
+ include Helpers::Ids
5
+
6
+ class InvalidValue < StandardError; end
7
+ VALID_PROJECT_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_]*$/
8
+
9
+ attr_reader(
10
+ :tests,
11
+ :rodauth,
12
+ :database,
13
+ :database_type,
14
+ :dev_db_url,
15
+ :db_gem,
16
+ :project_name,
17
+ :base
18
+ )
19
+
20
+ def tests=(val)
21
+ if ![minitest_id, rspec_id].include?(val)
22
+ raise InvalidValue, "Invalid test framework option"
23
+ end
24
+
25
+ @tests = val
26
+ end
27
+
28
+ def base=(val)
29
+ if ![fullstack_id, api_id].include?(val)
30
+ raise InvalidValue, "Invalid project option"
31
+ end
32
+
33
+ @base = val
34
+ end
35
+
36
+ def rodauth=(val)
37
+ val = false if ![true, false].include?(val)
38
+
39
+ @rodauth = val
40
+ end
41
+
42
+ def database=(val)
43
+ val = false if ![true, false].include?(val)
44
+
45
+ @database = val
46
+ end
47
+
48
+ def database_type=(val)
49
+ if ![mysql_id, postgresql_id, sqlite_id].include?(val)
50
+ raise InvalidValue, "Invalid database option"
51
+ end
52
+
53
+ @database_type = val
54
+
55
+ if mysql?
56
+ @dev_db_url = '"mysql2://user:password@localhost/app_#{environment}"'
57
+ @db_gem = "mysql2"
58
+ elsif postgresql?
59
+ @dev_db_url = '"postgres://user:password@localhost:5432/app_#{environment}"'
60
+ @db_gem = "pg"
61
+ else
62
+ @dev_db_url = '"sqlite://db/#{environment}.db"'
63
+ @db_gem = "sqlite3"
64
+ end
65
+ end
66
+
67
+ def project_name=(val)
68
+ if !(val =~ VALID_PROJECT_NAME_REGEX)
69
+ raise InvalidValue, "Project name must start with a letter and contains only letters, numbers and _"
70
+ end
71
+
72
+ @project_name = val
73
+ end
74
+
75
+ def rspec?
76
+ tests == rspec_id
77
+ end
78
+
79
+ def minitest?
80
+ tests == minitest_id
81
+ end
82
+
83
+ # rubocop:disable Lint/InterpolationCheck
84
+ def foo_bar_example
85
+ return 'view("bar")' if fullstack?
86
+
87
+ '{ foo: "bar" }'
88
+ end
89
+
90
+ def root_example
91
+ return 'view("index")' if fullstack?
92
+
93
+ '{ message: "#{t.hello.message}" }'
94
+ end
95
+ # rubocop:enable Lint/InterpolationCheck
96
+
97
+ def fullstack?
98
+ base == fullstack_id
99
+ end
100
+
101
+ def api?
102
+ base == api_id
103
+ end
104
+
105
+ def rodauth?
106
+ rodauth == true
107
+ end
108
+
109
+ def database?
110
+ database == true
111
+ end
112
+
113
+ def mysql?
114
+ return false unless database?
115
+
116
+ database_type == mysql_id
117
+ end
118
+
119
+ def postgresql?
120
+ return false unless database?
121
+
122
+ database_type == postgresql_id
123
+ end
124
+
125
+ def sqlite?
126
+ return false unless database?
127
+
128
+ database_type == sqlite_id
129
+ end
130
+
131
+ def const_project_name
132
+ @const_project_name ||= project_name.split('_').map(&:capitalize).join
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,15 @@
1
+ module Roda
2
+ module Project
3
+ module Helpers
4
+ module Ids
5
+ def fullstack_id = Roda::Project::FULLSTACK
6
+ def mysql_id = Roda::Project::MYSQL
7
+ def sqlite_id = Roda::Project::SQLITE
8
+ def postgresql_id = Roda::Project::POSTGRESQL
9
+ def api_id = Roda::Project::API
10
+ def rspec_id = Roda::Project::RSPEC
11
+ def minitest_id = Roda::Project::MINITEST
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ module Roda
2
+ module Project
3
+ module Helpers
4
+ module Input
5
+ def read_line(prompt, default)
6
+ val = reader.read_line(prompt).chomp
7
+ return default if val == ""
8
+ return false if val == "n"
9
+ return true if val == "Y" || val == "y"
10
+
11
+ val
12
+ end
13
+
14
+ def reader
15
+ @reader ||= TTY::Reader.new
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module Roda
2
+ module Project
3
+ module Helpers
4
+ module Template
5
+ def tty_cp_r(type, path)
6
+ TTY::File.copy_directory(
7
+ File.expand_path("../../templates/#{type}/#{path}", __dir__),
8
+ "#{@dir}#{@context.project_name}/#{path}",
9
+ context: @context
10
+ )
11
+ end
12
+
13
+ def tty_cp(type, path)
14
+ TTY::File.copy_file(
15
+ File.expand_path("../../templates/#{type}/#{path}", __dir__),
16
+ "#{@dir}#{@context.project_name}/#{path}",
17
+ context: @context
18
+ )
19
+ end
20
+
21
+ def cp_r(type, path)
22
+ FileUtils.cp_r(
23
+ File.expand_path("../../templates/#{type}/#{path}", __dir__),
24
+ "#{@dir}#{@context.project_name}/#{path}"
25
+ )
26
+ end
27
+
28
+ def cp(type, path)
29
+ File.write(
30
+ "#{@dir}#{@context.project_name}/#{path}",
31
+ File.read(File.expand_path("../../templates/#{type}/#{path}", __dir__))
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roda
4
+ module Project
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-file"
4
+ require "fileutils"
5
+ require "tty-reader"
6
+ require "pastel"
7
+ require_relative "project/version"
8
+ require_relative "project/helpers/ids"
9
+ require_relative "project/context"
10
+ require_relative "project/helpers/input"
11
+ require_relative "project/helpers/template"
12
+ require_relative "project/cli"
13
+
14
+ module Roda
15
+ module Project
16
+ class Error < StandardError; end
17
+
18
+ FULLSTACK = 1
19
+ API = 2
20
+ SQLITE = 1
21
+ POSTGRESQL = 2
22
+ MYSQL = 3
23
+ RSPEC = 1
24
+ MINITEST = 2
25
+
26
+ def self.messages
27
+ [
28
+ ['"What you do today can improve all your tomorrows." - Ralph Marston'],
29
+ ['"What you get by achieving your goals is not as important as what you become by achieving your goals." - Zig Ziglar'],
30
+ ['"Intelligence without ambition is a bird without wings." - Salvador Dali'],
31
+ ['"We may encounter many defeats but we must not be defeated." - May Angelou'],
32
+ ['"A creative man is motivated by the desire to achieve, not by the desire to beat others." - Ayn Rand'],
33
+ ['"A somebody was once a nobody who wanted to and did." - John Burroughs'],
34
+ ['"Courage is the first of human qualities because it is the quality which guarantees all others." - Winston Churchill'],
35
+ ['"The journey of a thousand miles begins with one step." - Lao Tzu'],
36
+ ['"Don’t worry about failures, worry about the chances you miss when you don’t even try." - Jack Canfield'],
37
+ ['"The secret to getting ahead is getting started." - Mark Twain'],
38
+ ['"The power of imagination makes us infinite." - John Muir'],
39
+ ['"Creativity is intelligence having fun." - Albert Einstein'],
40
+ ['"People who are crazy enough to think they can change the world, are the ones who do." - Rob Siltanen'],
41
+ ['"The way to get started is to quit talking and begin doing." - Walt Disney'],
42
+ ['"Success is not final, failure is not fatal: it is the courage to continue that counts." - Winston Churchill'],
43
+ ['"Less is almost always more. Simplicity is almost always the answer." - Zat Rana'],
44
+ ['"It all starts and ends in the mind. The most crucial skill is how you think." - Zat Rana'],
45
+ ['"It is never too late to be what you might have been." - George Eliot'],
46
+ ['"It does not matter how slowly you go, so long as you do not stop." - Confucius'],
47
+ ['"Start where you are. Use what you have. Do what you can." - Arthur Ashe'],
48
+ ['"A goal is a dream with a deadline." - Napoleon Hill'],
49
+ ['"Things do not happen. Things are made to happen." - John F. Kennedy'],
50
+ ['"Quality is not an act, it is a habit." - Aristotle'],
51
+ ]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,87 @@
1
+ class <%= context.const_project_name %> < Roda
2
+ # Routing<% if context.fullstack? %>
3
+ plugin :hash_branch_view_subdir<% end %>
4
+ plugin :autoload_hash_branches
5
+ autoload_hash_branch_dir("./app/routes")
6
+ plugin :all_verbs
7
+ plugin :not_found
8
+ <% if context.fullstack? %>
9
+ # Views
10
+ plugin :partials, views: "app/views"
11
+ plugin :render, layout: "./layout"
12
+ plugin :content_for, append: false
13
+ plugin :flash
14
+ <% end %>
15
+ # Request / Response
16
+ plugin :halt
17
+ plugin :json
18
+ plugin :exception_page
19
+ plugin :caching
20
+ plugin :cookies
21
+ plugin :default_headers
22
+ plugin :content_security_policy do |csp|
23
+ # csp.default_src :none
24
+ # csp.img_src :self
25
+ # csp.style_src :self
26
+ # csp.script_src :self
27
+ # csp.font_src :self
28
+ # csp.form_action :self
29
+ # csp.base_uri :none
30
+ # csp.frame_ancestors :none
31
+ # csp.block_all_mixed_content
32
+ end
33
+
34
+ # CSRF Protection
35
+ plugin :route_csrf
36
+
37
+ # Other
38
+ plugin :common_logger, Providers::Logger.get
39
+ plugin :json_parser
40
+ plugin :sessions, secret: Config.get[:secret]
41
+ plugin :i18n, **Config.get[:i18n]
42
+ <% if context.rodauth? %><% if context.api? %>
43
+ # Authentication
44
+ plugin :rodauth, json: :only do
45
+ enable :jwt
46
+ jwt_secret Config.get[:jwt_secret]
47
+ <% else %>
48
+ # Authentication
49
+ plugin :rodauth do
50
+ enable :login, :logout, :create_account, :verify_account
51
+ <% end %>
52
+ accounts_table :accounts
53
+ password_hash_table :account_password_hashes
54
+ use_database_authentication_functions? false
55
+ # base_url "http://localhost:9292"
56
+ login_column :email
57
+ # Redirect logged in users to the wherever login redirects to
58
+ already_logged_in { redirect "/" }
59
+
60
+ hmac_secret Config.get[:hmac_secret]
61
+ end
62
+ <% end %>
63
+ def config = @config ||= Config.get
64
+ def self.branch(args, &) = hash_branch(args, &)<% if context.fullstack? %>
65
+ def html = @html ||= Views::Html.new(t)<% end %>
66
+
67
+ route do |r|
68
+ r.hash_branches
69
+ # session[:locale] = 'pt-br'
70
+ # r.i18n_set_locale_from(:session)
71
+ <% if context.rodauth? %>
72
+ r.rodauth
73
+ rodauth.require_authentication
74
+ <% end %>
75
+ r.root do
76
+ <%= context.root_example %>
77
+ end
78
+ end
79
+
80
+ error do |e|
81
+ next exception_page(e, css_file: "/public/exception_page.css") if Config.not_production?
82
+ end
83
+
84
+ not_found do
85
+ "not found"
86
+ end
87
+ end
@@ -0,0 +1,9 @@
1
+ Act as a Ruby specialist.
2
+
3
+ This is a web application written using the Roda web framework, Sequel gem for database connection and RSpec for tests.
4
+
5
+ ## Project guidelines
6
+
7
+ - **Never** deliver code without RSpec tests validating the code (execute with `rake test`)
8
+ - **Never** write long comments in the code
9
+ - **Always** use clean code
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Base
6
+ gem "roda"
7
+ gem "roda-i18n"
8
+ gem "zeitwerk"
9
+ <% if context.rodauth? %>
10
+ # Authentication
11
+ gem "rodauth"
12
+ gem "jwt"
13
+ <% end %>
14
+ # Database
15
+ gem "sequel"
16
+ <%= "gem \"#{context.db_gem}\"" if context.database? %>
17
+
18
+ # Web Server
19
+ gem "puma"
20
+ # gem "falcon"
21
+ # gem 'iodine'
22
+ # gem 'thin'
23
+
24
+ # Performance
25
+ gem "oj"
26
+ # gem 'async'
27
+
28
+ # CLI
29
+ gem "rake"
30
+
31
+ # Security
32
+ # gem "rack-attack"
33
+
34
+ # Misc
35
+ gem "html_slice"
36
+ gem "mail"
37
+ gem "bcrypt"
38
+
39
+ group :development do
40
+ gem "guard-puma"
41
+ gem "guard-livereload"
42
+ gem "rack-livereload"
43
+ gem "rack-test"
44
+ gem "debug"
45
+ gem "base64"
46
+ gem "standard"<% if context.minitest? %>
47
+ gem "minitest"
48
+ gem "minitest-hooks"
49
+ <% else %>
50
+ gem "rspec"<% end %>
51
+ end
@@ -0,0 +1,25 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ guard "puma" do
19
+ watch("Gemfile.lock")
20
+ watch(%r{^app|i18n|public/.*})
21
+ end
22
+
23
+ guard "livereload" do
24
+ watch(%r{^app|i18n|public/.*})
25
+ end
@@ -0,0 +1,29 @@
1
+ # Rackr project scaffold
2
+
3
+ ### Running
4
+
5
+ 1. `$ bundle install`
6
+ 2. `$ yarn`
7
+ 3. `$ bin/dev`
8
+
9
+ for watch and compile assets:
10
+ 1. `$ bin/dev-assets`
11
+
12
+ ### Migrations
13
+
14
+ - `$ bin/db/migrate`
15
+
16
+ ### Included
17
+
18
+ gems:
19
+ - `roda` for routes
20
+ - `sequel` + `sqlite3` for database work
21
+ - `rerun` for reload after changes
22
+ - `rspec` for tests
23
+ - `zeitwerk` for code load
24
+
25
+ js:
26
+ - `@hotwired/turbo`
27
+
28
+ assets:
29
+ - `esbuild` for bundle js assets