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.
- checksums.yaml +7 -0
- data/bin/console +11 -0
- data/bin/roda-project +6 -0
- data/bin/roda-project.rb +9 -0
- data/bin/setup +8 -0
- data/lib/roda/project/cli.rb +134 -0
- data/lib/roda/project/context.rb +136 -0
- data/lib/roda/project/helpers/ids.rb +15 -0
- data/lib/roda/project/helpers/input.rb +20 -0
- data/lib/roda/project/helpers/template.rb +37 -0
- data/lib/roda/project/version.rb +7 -0
- data/lib/roda/project.rb +54 -0
- data/lib/roda/templates/base/app/app.rb.erb +87 -0
- data/lib/roda/templates/base/scaffold/AGENTS.md +9 -0
- data/lib/roda/templates/base/scaffold/Gemfile.erb +51 -0
- data/lib/roda/templates/base/scaffold/Guardfile +25 -0
- data/lib/roda/templates/base/scaffold/README.md +29 -0
- data/lib/roda/templates/base/scaffold/Rakefile.erb +209 -0
- data/lib/roda/templates/base/scaffold/app/config/config.rb.erb +25 -0
- data/lib/roda/templates/base/scaffold/app/config/locales/en.yml +273 -0
- data/lib/roda/templates/base/scaffold/app/config/locales/foo/en.yml +2 -0
- data/lib/roda/templates/base/scaffold/app/config/locales/foo/pt-br.yml +2 -0
- data/lib/roda/templates/base/scaffold/app/config/locales/pt-br.yml +244 -0
- data/lib/roda/templates/base/scaffold/app/config/providers/logger.rb +9 -0
- data/lib/roda/templates/base/scaffold/app/config/providers/mailer.rb +11 -0
- data/lib/roda/templates/base/scaffold/app/routes/foo.rb.erb +7 -0
- data/lib/roda/templates/base/scaffold/boot.rb.erb +35 -0
- data/lib/roda/templates/base/scaffold/config.ru.erb +13 -0
- data/lib/roda/templates/base/scaffold/public/css/app.css +1 -0
- data/lib/roda/templates/base/scaffold/public/exception_page.css +16 -0
- data/lib/roda/templates/base/scaffold/public/images/roda-project.png +0 -0
- data/lib/roda/templates/base/scaffold/public/js/app.js +27 -0
- data/lib/roda/templates/database/app/config/providers/db/conn.rb +15 -0
- data/lib/roda/templates/database/db/seeds.rb +1 -0
- data/lib/roda/templates/front-end/app/assets/css/app.css +20 -0
- data/lib/roda/templates/front-end/app/assets/js/app.js +7 -0
- data/lib/roda/templates/front-end/app/assets/js/some/foo.js +5 -0
- data/lib/roda/templates/front-end/app/views/foo/bar.erb +1 -0
- data/lib/roda/templates/front-end/app/views/foo/html.rb +6 -0
- data/lib/roda/templates/front-end/app/views/html.rb +22 -0
- data/lib/roda/templates/front-end/app/views/index.erb +1 -0
- data/lib/roda/templates/front-end/app/views/layout.erb +13 -0
- data/lib/roda/templates/front-end/esbuild.js +39 -0
- data/lib/roda/templates/front-end/package.json +20 -0
- data/lib/roda/templates/rodauth/app/models/account.rb +2 -0
- data/lib/roda/templates/rodauth/app/views/create-account.erb +9 -0
- data/lib/roda/templates/rodauth/db/migrations/001_add_rodauth.rb +71 -0
- data/lib/roda/templates/tests/minitest/spec/app/app_spec.rb.erb +15 -0
- data/lib/roda/templates/tests/minitest/spec/app/routes/foo_spec.rb +8 -0
- data/lib/roda/templates/tests/minitest/spec/app/routes/test_branch_spec.rb +4 -0
- data/lib/roda/templates/tests/minitest/spec/app/views/html_spec.rb +0 -0
- data/lib/roda/templates/tests/minitest/spec/spec_helper.rb.erb +33 -0
- data/lib/roda/templates/tests/rspec/spec/app/app_spec.rb.erb +15 -0
- data/lib/roda/templates/tests/rspec/spec/app/routes/foo_spec.rb +8 -0
- data/lib/roda/templates/tests/rspec/spec/app/routes/test_branch_spec.rb +4 -0
- data/lib/roda/templates/tests/rspec/spec/app/views/html_spec.rb +0 -0
- data/lib/roda/templates/tests/rspec/spec/spec_helper.rb.erb +19 -0
- 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
data/bin/roda-project.rb
ADDED
data/bin/setup
ADDED
|
@@ -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
|
data/lib/roda/project.rb
ADDED
|
@@ -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
|