hanami 0.0.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +214 -0
- data/FEATURES.md +156 -0
- data/LICENSE.md +22 -0
- data/README.md +80 -15
- data/bin/hanami +5 -0
- data/hanami.gemspec +27 -12
- data/lib/hanami.rb +78 -2
- data/lib/hanami/action/csrf_protection.rb +167 -0
- data/lib/hanami/action/routing_helpers.rb +40 -0
- data/lib/hanami/application.rb +244 -0
- data/lib/hanami/application_name.rb +101 -0
- data/lib/hanami/cli.rb +119 -0
- data/lib/hanami/cli_sub_commands/assets.rb +29 -0
- data/lib/hanami/cli_sub_commands/db.rb +124 -0
- data/lib/hanami/cli_sub_commands/destroy.rb +102 -0
- data/lib/hanami/cli_sub_commands/generate.rb +127 -0
- data/lib/hanami/commands/assets/precompile.rb +35 -0
- data/lib/hanami/commands/console.rb +90 -0
- data/lib/hanami/commands/db/abstract.rb +19 -0
- data/lib/hanami/commands/db/apply.rb +14 -0
- data/lib/hanami/commands/db/console.rb +50 -0
- data/lib/hanami/commands/db/create.rb +14 -0
- data/lib/hanami/commands/db/drop.rb +14 -0
- data/lib/hanami/commands/db/migrate.rb +19 -0
- data/lib/hanami/commands/db/prepare.rb +14 -0
- data/lib/hanami/commands/db/version.rb +14 -0
- data/lib/hanami/commands/generate/abstract.rb +63 -0
- data/lib/hanami/commands/generate/action.rb +262 -0
- data/lib/hanami/commands/generate/app.rb +116 -0
- data/lib/hanami/commands/generate/mailer.rb +118 -0
- data/lib/hanami/commands/generate/migration.rb +63 -0
- data/lib/hanami/commands/generate/model.rb +96 -0
- data/lib/hanami/commands/new/abstract.rb +128 -0
- data/lib/hanami/commands/new/app.rb +116 -0
- data/lib/hanami/commands/new/container.rb +102 -0
- data/lib/hanami/commands/routes.rb +41 -0
- data/lib/hanami/commands/server.rb +79 -0
- data/lib/hanami/config/configure.rb +17 -0
- data/lib/hanami/config/cookies.rb +68 -0
- data/lib/hanami/config/framework_configuration.rb +42 -0
- data/lib/hanami/config/load_paths.rb +27 -0
- data/lib/hanami/config/mapper.rb +36 -0
- data/lib/hanami/config/mapping.rb +12 -0
- data/lib/hanami/config/routes.rb +16 -0
- data/lib/hanami/config/security.rb +58 -0
- data/lib/hanami/config/sessions.rb +97 -0
- data/lib/hanami/configuration.rb +1728 -0
- data/lib/hanami/container.rb +59 -0
- data/lib/hanami/environment.rb +485 -0
- data/lib/hanami/frameworks.rb +14 -0
- data/lib/hanami/generators/action/action.rb.tt +8 -0
- data/lib/hanami/generators/action/action_spec.minitest.tt +12 -0
- data/lib/hanami/generators/action/action_spec.rspec.tt +11 -0
- data/lib/hanami/generators/action/action_without_view.rb.tt +9 -0
- data/lib/hanami/generators/action/template.tt +0 -0
- data/lib/hanami/generators/action/view.rb.tt +5 -0
- data/lib/hanami/generators/action/view_spec.minitest.tt +13 -0
- data/lib/hanami/generators/action/view_spec.rspec.tt +12 -0
- data/lib/hanami/generators/app/.gitkeep.tt +1 -0
- data/lib/hanami/generators/app/application.rb.tt +273 -0
- data/lib/hanami/generators/app/config/initializers/.gitkeep +0 -0
- data/lib/hanami/generators/app/config/routes.rb.tt +2 -0
- data/lib/hanami/generators/app/favicon.ico +0 -0
- data/lib/hanami/generators/app/templates/application.html.erb.tt +10 -0
- data/lib/hanami/generators/app/views/application_layout.rb.tt +7 -0
- data/lib/hanami/generators/application/app/.env.development.tt +4 -0
- data/lib/hanami/generators/application/app/.env.test.tt +4 -0
- data/lib/hanami/generators/application/app/.env.tt +1 -0
- data/lib/hanami/generators/application/app/.gitignore +0 -0
- data/lib/hanami/generators/application/app/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/Gemfile.tt +37 -0
- data/lib/hanami/generators/application/app/Rakefile.minitest.tt +11 -0
- data/lib/hanami/generators/application/app/Rakefile.rspec.tt +6 -0
- data/lib/hanami/generators/application/app/apps/.gitkeep.tt +1 -0
- data/lib/hanami/generators/application/app/capybara.rb.rspec.tt +8 -0
- data/lib/hanami/generators/application/app/config.ru.tt +3 -0
- data/lib/hanami/generators/application/app/config/application.rb.tt +270 -0
- data/lib/hanami/generators/application/app/config/environment.rb.tt +5 -0
- data/lib/hanami/generators/application/app/config/initializers/.gitkeep +0 -0
- data/lib/hanami/generators/application/app/config/routes.rb.tt +2 -0
- data/lib/hanami/generators/application/app/db/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/favicon.ico +0 -0
- data/lib/hanami/generators/application/app/features_helper.rb.minitest.tt +11 -0
- data/lib/hanami/generators/application/app/features_helper.rb.rspec.tt +12 -0
- data/lib/hanami/generators/application/app/gitignore.tt +2 -0
- data/lib/hanami/generators/application/app/gitignore_with_db.tt +4 -0
- data/lib/hanami/generators/application/app/hanamirc.tt +3 -0
- data/lib/hanami/generators/application/app/lib/app_name.rb.tt +59 -0
- data/lib/hanami/generators/application/app/lib/chirp/entities/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/lib/chirp/repositories/.gitkeep +1 -0
- data/lib/hanami/generators/application/app/lib/config/mapping.rb.tt +7 -0
- data/lib/hanami/generators/application/app/rspec.rspec.tt +2 -0
- data/lib/hanami/generators/application/app/schema.sql.tt +0 -0
- data/lib/hanami/generators/application/app/spec_helper.rb.minitest.tt +7 -0
- data/lib/hanami/generators/application/app/spec_helper.rb.rspec.tt +104 -0
- data/lib/hanami/generators/application/app/templates/application.html.erb.tt +10 -0
- data/lib/hanami/generators/application/app/views/application_layout.rb.tt +7 -0
- data/lib/hanami/generators/application/container/.env.development.tt +3 -0
- data/lib/hanami/generators/application/container/.env.test.tt +3 -0
- data/lib/hanami/generators/application/container/.env.tt +1 -0
- data/lib/hanami/generators/application/container/.gitignore +0 -0
- data/lib/hanami/generators/application/container/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/Gemfile.tt +36 -0
- data/lib/hanami/generators/application/container/Rakefile.minitest.tt +11 -0
- data/lib/hanami/generators/application/container/Rakefile.rspec.tt +6 -0
- data/lib/hanami/generators/application/container/capybara.rb.rspec.tt +8 -0
- data/lib/hanami/generators/application/container/config.ru.tt +3 -0
- data/lib/hanami/generators/application/container/config/environment.rb.tt +7 -0
- data/lib/hanami/generators/application/container/config/initializers/.gitkeep +0 -0
- data/lib/hanami/generators/application/container/db/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/features_helper.rb.minitest.tt +11 -0
- data/lib/hanami/generators/application/container/features_helper.rb.rspec.tt +12 -0
- data/lib/hanami/generators/application/container/gitignore.tt +2 -0
- data/lib/hanami/generators/application/container/gitignore_with_db.tt +4 -0
- data/lib/hanami/generators/application/container/hanamirc.tt +3 -0
- data/lib/hanami/generators/application/container/lib/app_name.rb.tt +60 -0
- data/lib/hanami/generators/application/container/lib/chirp/entities/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/lib/chirp/mailers/.gitkeep +0 -0
- data/lib/hanami/generators/application/container/lib/chirp/mailers/templates/.gitkeep +0 -0
- data/lib/hanami/generators/application/container/lib/chirp/repositories/.gitkeep +1 -0
- data/lib/hanami/generators/application/container/lib/config/mapping.rb.tt +7 -0
- data/lib/hanami/generators/application/container/rspec.rspec.tt +2 -0
- data/lib/hanami/generators/application/container/schema.sql.tt +0 -0
- data/lib/hanami/generators/application/container/spec_helper.rb.minitest.tt +7 -0
- data/lib/hanami/generators/application/container/spec_helper.rb.rspec.tt +104 -0
- data/lib/hanami/generators/database_config.rb +99 -0
- data/lib/hanami/generators/generatable.rb +51 -0
- data/lib/hanami/generators/generator.rb +35 -0
- data/lib/hanami/generators/mailer/mailer.rb.tt +7 -0
- data/lib/hanami/generators/mailer/mailer_spec.rb.tt +7 -0
- data/lib/hanami/generators/mailer/template.html.tt +0 -0
- data/lib/hanami/generators/mailer/template.txt.tt +0 -0
- data/lib/hanami/generators/migration/migration.rb.tt +4 -0
- data/lib/hanami/generators/model/entity.rb.tt +3 -0
- data/lib/hanami/generators/model/entity_spec.minitest.tt +5 -0
- data/lib/hanami/generators/model/entity_spec.rspec.tt +3 -0
- data/lib/hanami/generators/model/repository.rb.tt +3 -0
- data/lib/hanami/generators/model/repository_spec.minitest.tt +5 -0
- data/lib/hanami/generators/model/repository_spec.rspec.tt +3 -0
- data/lib/hanami/generators/test_framework.rb +42 -0
- data/lib/hanami/hanamirc.rb +152 -0
- data/lib/hanami/loader.rb +258 -0
- data/lib/hanami/mailer/glue.rb +68 -0
- data/lib/hanami/middleware.rb +143 -0
- data/lib/hanami/rake_helper.rb +68 -0
- data/lib/hanami/rake_tasks.rb +2 -0
- data/lib/hanami/rendering_policy.rb +77 -0
- data/lib/hanami/repositories/car_repository.rb +3 -0
- data/lib/hanami/repositories/name_repository.rb +3 -0
- data/lib/hanami/root.rb +7 -0
- data/lib/hanami/routes.rb +151 -0
- data/lib/hanami/routing/default.rb +25 -0
- data/lib/hanami/setup.rb +3 -0
- data/lib/hanami/static.rb +77 -0
- data/lib/hanami/templates/default.html.erb +9 -0
- data/lib/hanami/templates/welcome.html.erb +52 -0
- data/lib/hanami/version.rb +4 -1
- data/lib/hanami/views/default.rb +34 -0
- data/lib/hanami/views/default_template_finder.rb +20 -0
- data/lib/hanami/views/null_view.rb +17 -0
- data/lib/hanami/welcome.rb +40 -0
- metadata +357 -16
- data/.gitignore +0 -9
- data/Gemfile +0 -4
- data/Rakefile +0 -2
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Generators
|
5
|
+
class DatabaseConfig
|
6
|
+
|
7
|
+
SUPPORTED_ENGINES = {
|
8
|
+
'mysql' => { type: :sql, mri: 'mysql2', jruby: 'jdbc-mysql' },
|
9
|
+
'mysql2' => { type: :sql, mri: 'mysql2', jruby: 'jdbc-mysql' },
|
10
|
+
'postgresql' => { type: :sql, mri: 'pg', jruby: 'jdbc-postgres' },
|
11
|
+
'postgres' => { type: :sql, mri: 'pg', jruby: 'jdbc-postgres' },
|
12
|
+
'sqlite' => { type: :sql, mri: 'sqlite3', jruby: 'jdbc-sqlite3' },
|
13
|
+
'sqlite3' => { type: :sql, mri: 'sqlite3', jruby: 'jdbc-sqlite3' },
|
14
|
+
'filesystem' => { type: :file_system, mri: nil, jruby: nil },
|
15
|
+
'memory' => { type: :memory, mri: nil, jruby: nil }
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
DEFAULT_ENGINE = 'filesystem'.freeze
|
19
|
+
|
20
|
+
attr_reader :engine, :name
|
21
|
+
|
22
|
+
def initialize(engine, name)
|
23
|
+
@engine = engine
|
24
|
+
@name = name
|
25
|
+
|
26
|
+
SUPPORTED_ENGINES.key?(engine.to_s) or fail "\"#{ engine }\" is not a valid database type"
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_hash
|
30
|
+
{
|
31
|
+
gem: gem,
|
32
|
+
uri: uri,
|
33
|
+
type: type
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def type
|
38
|
+
SUPPORTED_ENGINES[engine][:type]
|
39
|
+
end
|
40
|
+
|
41
|
+
def sql?
|
42
|
+
type == :sql
|
43
|
+
end
|
44
|
+
|
45
|
+
def filesystem?
|
46
|
+
type == :file_system
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def platform
|
52
|
+
Hanami::Utils.jruby? ? :jruby : :mri
|
53
|
+
end
|
54
|
+
|
55
|
+
def platform_prefix
|
56
|
+
'jdbc:'.freeze if Hanami::Utils.jruby?
|
57
|
+
end
|
58
|
+
|
59
|
+
def uri
|
60
|
+
{
|
61
|
+
development: environment_uri(:development),
|
62
|
+
test: environment_uri(:test)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def gem
|
67
|
+
SUPPORTED_ENGINES[engine][platform]
|
68
|
+
end
|
69
|
+
|
70
|
+
def base_uri
|
71
|
+
case engine
|
72
|
+
when 'mysql', 'mysql2'
|
73
|
+
if Hanami::Utils.jruby?
|
74
|
+
"mysql://localhost/#{ name }"
|
75
|
+
else
|
76
|
+
"mysql2://localhost/#{ name }"
|
77
|
+
end
|
78
|
+
when 'postgresql', 'postgres'
|
79
|
+
"postgres://localhost/#{ name }"
|
80
|
+
when 'sqlite', 'sqlite3'
|
81
|
+
"sqlite://db/#{ Shellwords.escape(name) }"
|
82
|
+
when 'memory'
|
83
|
+
"memory://localhost/#{ name }"
|
84
|
+
when 'filesystem'
|
85
|
+
"file:///db/#{ Shellwords.escape(name) }"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def environment_uri(environment)
|
90
|
+
case engine
|
91
|
+
when 'sqlite', 'sqlite3'
|
92
|
+
"#{ platform_prefix }#{ base_uri }_#{ environment }.sqlite"
|
93
|
+
else
|
94
|
+
"#{ platform_prefix if sql? }#{ base_uri }_#{ environment }"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'hanami/generators/generator'
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Generators
|
5
|
+
module Generatable
|
6
|
+
|
7
|
+
def start
|
8
|
+
map_templates
|
9
|
+
process_templates
|
10
|
+
end
|
11
|
+
|
12
|
+
def destroy
|
13
|
+
generator.behavior = :revoke
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def generator
|
18
|
+
@generator ||= Hanami::Generators::Generator.new(template_source_path, target_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def map_templates
|
22
|
+
raise NotImplementedError, "must implement the map_templates method"
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_mapping(source, target)
|
26
|
+
generator.add_mapping(source, target)
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_templates
|
30
|
+
generator.process_templates(template_options)
|
31
|
+
post_process_templates
|
32
|
+
end
|
33
|
+
|
34
|
+
def post_process_templates
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def template_options
|
39
|
+
{}
|
40
|
+
end
|
41
|
+
|
42
|
+
def template_source_path
|
43
|
+
raise NotImplementedError, "must implement the template_source_path method"
|
44
|
+
end
|
45
|
+
|
46
|
+
def target_path
|
47
|
+
raise NotImplementedError, "must implement the target_path method"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Hanami
|
5
|
+
module Generators
|
6
|
+
class Generator
|
7
|
+
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def_delegators :@processor, :run, :behavior=, :inject_into_file, :append_to_file, :prepend_to_file
|
11
|
+
|
12
|
+
class Processor < Thor
|
13
|
+
include Thor::Actions
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(template_source_path, target_path)
|
17
|
+
@template_source_path = template_source_path
|
18
|
+
@target_path = target_path
|
19
|
+
@template_mappings = []
|
20
|
+
@processor = Processor.new
|
21
|
+
@processor.class.source_root(@template_source_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_mapping(source, target)
|
25
|
+
@template_mappings << [source, target]
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_templates(options = {})
|
29
|
+
@template_mappings.each do |src, dst|
|
30
|
+
@processor.template(@template_source_path.join(src), @target_path.join(dst), options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
File without changes
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'hanami/hanamirc'
|
2
|
+
module Hanami
|
3
|
+
module Generators
|
4
|
+
class TestFramework
|
5
|
+
RSPEC = 'rspec'.freeze
|
6
|
+
MINITEST = 'minitest'.freeze
|
7
|
+
VALID_FRAMEWORKS = [RSPEC, MINITEST].freeze
|
8
|
+
|
9
|
+
attr_reader :framework
|
10
|
+
|
11
|
+
def initialize(hanamirc, framework)
|
12
|
+
@framework = (framework || hanamirc.options.fetch(:test))
|
13
|
+
assert_framework!
|
14
|
+
end
|
15
|
+
|
16
|
+
def rspec?
|
17
|
+
framework == RSPEC
|
18
|
+
end
|
19
|
+
|
20
|
+
def minitest?
|
21
|
+
framework == MINITEST
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def assert_framework!
|
27
|
+
if !supported_framework?
|
28
|
+
raise ArgumentError.new("Unknown test framework '#{ framework}'. Please use one of #{ valid_test_frameworks.join(', ')}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid_test_frameworks
|
33
|
+
VALID_FRAMEWORKS.map { |name| "'#{ name }'"}
|
34
|
+
end
|
35
|
+
|
36
|
+
def supported_framework?
|
37
|
+
VALID_FRAMEWORKS.include?(framework)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'dotenv/parser'
|
3
|
+
require 'hanami/utils/hash'
|
4
|
+
|
5
|
+
module Hanami
|
6
|
+
# Read the .hanamirc file in the root of the application
|
7
|
+
#
|
8
|
+
# @since 0.3.0
|
9
|
+
# @api private
|
10
|
+
class Hanamirc
|
11
|
+
# Hanamirc name file
|
12
|
+
#
|
13
|
+
# @since 0.3.0
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
# @see Hanami::Hanamirc#path_file
|
17
|
+
FILE_NAME = '.hanamirc'.freeze
|
18
|
+
|
19
|
+
# Architecture default value
|
20
|
+
#
|
21
|
+
# @since 0.3.0
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
# @see Hanami::Hanamirc#options
|
25
|
+
DEFAULT_ARCHITECTURE = 'container'.freeze
|
26
|
+
|
27
|
+
# Application architecture value
|
28
|
+
#
|
29
|
+
# @since 0.6.0
|
30
|
+
# @api private
|
31
|
+
APP_ARCHITECTURE = 'app'.freeze
|
32
|
+
|
33
|
+
# Architecture key for writing the hanamirc file
|
34
|
+
#
|
35
|
+
# @since 0.3.0
|
36
|
+
# @api private
|
37
|
+
#
|
38
|
+
# @see Hanami::Hanamirc::DEFAULT_OPTIONS
|
39
|
+
ARCHITECTURE_KEY = 'architecture'.freeze
|
40
|
+
|
41
|
+
# Test suite default value
|
42
|
+
#
|
43
|
+
# @since 0.3.0
|
44
|
+
# @api private
|
45
|
+
#
|
46
|
+
# @see Hanami::Hanamirc::DEFAULT_OPTIONS
|
47
|
+
DEFAULT_TEST_SUITE = 'minitest'.freeze
|
48
|
+
|
49
|
+
# Test suite key for writing the hanamirc file
|
50
|
+
#
|
51
|
+
# @since 0.3.0
|
52
|
+
# @api private
|
53
|
+
#
|
54
|
+
# @see Hanami::Hanamirc::DEFAULT_OPTIONS
|
55
|
+
TEST_KEY = 'test'.freeze
|
56
|
+
|
57
|
+
# Template default value
|
58
|
+
#
|
59
|
+
# @since 0.3.0
|
60
|
+
# @api private
|
61
|
+
#
|
62
|
+
# @see Hanami::Hanamirc::DEFAULT_OPTIONS
|
63
|
+
DEFAULT_TEMPLATE = 'erb'.freeze
|
64
|
+
|
65
|
+
# Template key for writing the hanamirc file
|
66
|
+
#
|
67
|
+
# @since 0.3.0
|
68
|
+
# @api private
|
69
|
+
#
|
70
|
+
# @see Hanami::Hanamirc::DEFAULT_OPTIONS
|
71
|
+
TEMPLATE_KEY = 'template'.freeze
|
72
|
+
|
73
|
+
# Default values for writing the hanamirc file
|
74
|
+
#
|
75
|
+
# @since 0.5.1
|
76
|
+
# @api private
|
77
|
+
#
|
78
|
+
# @see Hanami::Hanamirc#options
|
79
|
+
DEFAULT_OPTIONS = Utils::Hash.new({
|
80
|
+
ARCHITECTURE_KEY => DEFAULT_ARCHITECTURE,
|
81
|
+
TEST_KEY => DEFAULT_TEST_SUITE,
|
82
|
+
TEMPLATE_KEY => DEFAULT_TEMPLATE
|
83
|
+
}).symbolize!.freeze
|
84
|
+
|
85
|
+
# Initialize Hanamirc class with application's root and environment options.
|
86
|
+
#
|
87
|
+
# @param root [Pathname] Application's root
|
88
|
+
#
|
89
|
+
# @see Hanami::Environment#initialize
|
90
|
+
def initialize(root)
|
91
|
+
@root = root
|
92
|
+
end
|
93
|
+
|
94
|
+
# Read hanamirc file (if exists) and parse it's values or return default.
|
95
|
+
#
|
96
|
+
# @return [Hanami::Utils::Hash] parsed values
|
97
|
+
#
|
98
|
+
# @example Default values if file doesn't exist
|
99
|
+
# Hanami::Hanamirc.new(Pathname.new(Dir.pwd)).options
|
100
|
+
# # => { architecture: 'container', test: 'minitest', template: 'erb' }
|
101
|
+
#
|
102
|
+
# @example Custom values if file doesn't exist
|
103
|
+
# options = { architect: 'application', test: 'rspec', template: 'slim' }
|
104
|
+
# Hanami::Hanamirc.new(Pathname.new(Dir.pwd), options).options
|
105
|
+
# # => { architecture: 'application', test: 'rspec', template: 'slim' }
|
106
|
+
def options
|
107
|
+
@options ||= symbolize(DEFAULT_OPTIONS.merge(file_options))
|
108
|
+
end
|
109
|
+
|
110
|
+
# Check if hanamirc file exists
|
111
|
+
#
|
112
|
+
# @since 0.3.0
|
113
|
+
# @api private
|
114
|
+
#
|
115
|
+
# @return [Boolean] hanamirc file's path existing
|
116
|
+
def exists?
|
117
|
+
path_file.exist?
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def symbolize(hash)
|
123
|
+
Utils::Hash.new(hash).symbolize!
|
124
|
+
end
|
125
|
+
|
126
|
+
def file_options
|
127
|
+
symbolize(exists? ? Dotenv::Parser.call(content) : {})
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return the hanamirc file's path
|
131
|
+
#
|
132
|
+
# @since 0.3.0
|
133
|
+
# @api private
|
134
|
+
#
|
135
|
+
# @return [Pathname] hanamirc file's path
|
136
|
+
#
|
137
|
+
# @see Hanami::Hanamirc::FILE_NAME
|
138
|
+
def path_file
|
139
|
+
@root.join FILE_NAME
|
140
|
+
end
|
141
|
+
|
142
|
+
# Return the content of hanamirc file
|
143
|
+
#
|
144
|
+
# @since 0.3.0
|
145
|
+
# @api private
|
146
|
+
#
|
147
|
+
# @return [String] content of hanamirc file
|
148
|
+
def content
|
149
|
+
path_file.read
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require 'hanami/utils/class'
|
2
|
+
require 'hanami/utils/kernel'
|
3
|
+
require 'hanami/utils/string'
|
4
|
+
require 'hanami/routes'
|
5
|
+
require 'hanami/routing/default'
|
6
|
+
require 'hanami/action/session'
|
7
|
+
require 'hanami/config/security'
|
8
|
+
require 'hanami/action/routing_helpers'
|
9
|
+
|
10
|
+
module Hanami
|
11
|
+
# Load an application
|
12
|
+
#
|
13
|
+
# @since 0.1.0
|
14
|
+
# @api private
|
15
|
+
class Loader
|
16
|
+
|
17
|
+
STRICT_TRANSPORT_SECURITY_HEADER = 'Strict-Transport-Security'.freeze
|
18
|
+
STRICT_TRANSPORT_SECURITY_DEFAULT_VALUE = 'max-age=31536000'.freeze
|
19
|
+
|
20
|
+
def initialize(application)
|
21
|
+
@application = application
|
22
|
+
@configuration = @application.configuration
|
23
|
+
|
24
|
+
@mutex = Mutex.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def load!
|
28
|
+
@mutex.synchronize do
|
29
|
+
load_configuration!
|
30
|
+
configure_frameworks!
|
31
|
+
load_configuration_load_paths!
|
32
|
+
load_rack!
|
33
|
+
load_frameworks!
|
34
|
+
load_initializers!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
attr_reader :application, :configuration
|
40
|
+
|
41
|
+
def load_configuration!
|
42
|
+
configuration.load!(application_module)
|
43
|
+
end
|
44
|
+
|
45
|
+
def configure_frameworks!
|
46
|
+
_configure_model_framework! if defined?(Hanami::Model)
|
47
|
+
_configure_controller_framework!
|
48
|
+
_configure_view_framework!
|
49
|
+
_configure_assets_framework!
|
50
|
+
_configure_logger!
|
51
|
+
end
|
52
|
+
|
53
|
+
def _configure_controller_framework!
|
54
|
+
config = configuration
|
55
|
+
unless namespace.const_defined?('Controller')
|
56
|
+
controller = Hanami::Controller.duplicate(namespace) do
|
57
|
+
handle_exceptions config.handle_exceptions
|
58
|
+
default_request_format config.default_request_format
|
59
|
+
default_response_format config.default_response_format
|
60
|
+
default_headers({
|
61
|
+
Hanami::Config::Security::X_FRAME_OPTIONS_HEADER => config.security.x_frame_options,
|
62
|
+
Hanami::Config::Security::CONTENT_SECURITY_POLICY_HEADER => config.security.content_security_policy
|
63
|
+
})
|
64
|
+
default_headers.merge!(STRICT_TRANSPORT_SECURITY_HEADER => STRICT_TRANSPORT_SECURITY_DEFAULT_VALUE) if config.force_ssl
|
65
|
+
|
66
|
+
if config.cookies.enabled?
|
67
|
+
require 'hanami/action/cookies'
|
68
|
+
prepare { include Hanami::Action::Cookies }
|
69
|
+
cookies config.cookies.default_options
|
70
|
+
end
|
71
|
+
|
72
|
+
if config.sessions.enabled?
|
73
|
+
prepare do
|
74
|
+
include Hanami::Action::Session
|
75
|
+
include Hanami::Action::CSRFProtection
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
prepare { include Hanami::Action::RoutingHelpers }
|
80
|
+
|
81
|
+
config.controller.__apply(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
namespace.const_set('Controller', controller)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def _configure_view_framework!
|
89
|
+
config = configuration
|
90
|
+
unless namespace.const_defined?('View')
|
91
|
+
view = Hanami::View.duplicate(namespace) do
|
92
|
+
root config.templates
|
93
|
+
layout config.layout
|
94
|
+
|
95
|
+
config.view.__apply(self)
|
96
|
+
end
|
97
|
+
|
98
|
+
namespace.const_set('View', view)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _configure_assets_framework!
|
103
|
+
config = configuration
|
104
|
+
|
105
|
+
unless application_module.const_defined?('Assets')
|
106
|
+
assets = Hanami::Assets.duplicate(namespace) do
|
107
|
+
root config.root
|
108
|
+
|
109
|
+
scheme config.scheme
|
110
|
+
host config.host
|
111
|
+
port config.port
|
112
|
+
|
113
|
+
public_directory Hanami.public_directory
|
114
|
+
prefix Utils::PathPrefix.new('/assets').join(config.path_prefix)
|
115
|
+
|
116
|
+
manifest Hanami.public_directory.join('assets.json')
|
117
|
+
compile true
|
118
|
+
|
119
|
+
config.assets.__apply(self)
|
120
|
+
end
|
121
|
+
|
122
|
+
assets.configure do
|
123
|
+
cdn host != config.host
|
124
|
+
end
|
125
|
+
|
126
|
+
application_module.const_set('Assets', assets)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def _configure_model_framework!
|
131
|
+
config = configuration
|
132
|
+
if _hanami_model_loaded? && !application_module.const_defined?('Model')
|
133
|
+
model = Hanami::Model.duplicate(application_module) do
|
134
|
+
adapter(config.adapter) if config.adapter
|
135
|
+
mapping(&config.mapping) if config.mapping
|
136
|
+
|
137
|
+
config.model.__apply(self)
|
138
|
+
end
|
139
|
+
|
140
|
+
application_module.const_set('Model', model)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def _configure_logger!
|
145
|
+
unless application_module.const_defined?('Logger', false)
|
146
|
+
if configuration.logger.nil?
|
147
|
+
configuration.logger Hanami::Logger.new(application_module.to_s)
|
148
|
+
end
|
149
|
+
application_module.const_set('Logger', configuration.logger)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def load_frameworks!
|
154
|
+
_load_view_framework!
|
155
|
+
_load_assets_framework!
|
156
|
+
_load_model_framework!
|
157
|
+
end
|
158
|
+
|
159
|
+
def _load_view_framework!
|
160
|
+
namespace.module_eval %{
|
161
|
+
#{ namespace }::View.load!
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
def _load_assets_framework!
|
166
|
+
application_module.module_eval %{
|
167
|
+
#{ application_module }::Assets.load!
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
171
|
+
def _load_model_framework!
|
172
|
+
return unless _load_model_framework?
|
173
|
+
|
174
|
+
application_module.module_eval %{
|
175
|
+
#{ application_module }::Model.load!
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
def _load_model_framework?
|
180
|
+
if _hanami_model_loaded? && application_module.const_defined?('Model')
|
181
|
+
model = application_module.const_get('Model')
|
182
|
+
model.configuration.adapter
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def _hanami_model_loaded?
|
187
|
+
defined?(Hanami::Model)
|
188
|
+
end
|
189
|
+
|
190
|
+
def _hanami_mailer_loaded?
|
191
|
+
defined?(Hanami::Mailer)
|
192
|
+
end
|
193
|
+
|
194
|
+
def load_configuration_load_paths!
|
195
|
+
configuration.load_paths.load!(configuration.root)
|
196
|
+
end
|
197
|
+
|
198
|
+
def load_rack!
|
199
|
+
_assign_routes_to_application_module!
|
200
|
+
|
201
|
+
return if application.is_a?(Class)
|
202
|
+
_assign_rendering_policy!
|
203
|
+
_assign_rack_routes!
|
204
|
+
_load_rack_middleware!
|
205
|
+
end
|
206
|
+
|
207
|
+
def _assign_rendering_policy!
|
208
|
+
application.renderer = RenderingPolicy.new(configuration)
|
209
|
+
end
|
210
|
+
|
211
|
+
def _assign_rack_routes!
|
212
|
+
application.routes = application_routes
|
213
|
+
end
|
214
|
+
|
215
|
+
def _load_rack_middleware!
|
216
|
+
configuration.middleware.load!(application, namespace)
|
217
|
+
end
|
218
|
+
|
219
|
+
def _assign_routes_to_application_module!
|
220
|
+
unless application_module.const_defined?('Routes')
|
221
|
+
routes = Hanami::Routes.new(application_routes)
|
222
|
+
application_module.const_set('Routes', routes)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def application_module
|
227
|
+
@application_module ||= Utils::Class.load!(
|
228
|
+
Utils::String.new(application.name).namespace
|
229
|
+
)
|
230
|
+
end
|
231
|
+
|
232
|
+
def application_routes
|
233
|
+
resolver = Hanami::Routing::EndpointResolver.new(pattern: configuration.controller_pattern, namespace: namespace)
|
234
|
+
default_app = Hanami::Routing::Default.new
|
235
|
+
Hanami::Router.new(
|
236
|
+
parsers: configuration.body_parsers,
|
237
|
+
resolver: resolver,
|
238
|
+
default_app: default_app,
|
239
|
+
scheme: configuration.scheme,
|
240
|
+
host: configuration.host,
|
241
|
+
port: configuration.port,
|
242
|
+
prefix: configuration.path_prefix,
|
243
|
+
force_ssl: configuration.force_ssl,
|
244
|
+
&configuration.routes
|
245
|
+
)
|
246
|
+
end
|
247
|
+
|
248
|
+
def namespace
|
249
|
+
configuration.namespace || application_module
|
250
|
+
end
|
251
|
+
|
252
|
+
def load_initializers!
|
253
|
+
Dir["#{configuration.root}/config/initializers/**/*.rb"].each do |file|
|
254
|
+
require file
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|