lb-project 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +41 -0
  3. data/.rspec +6 -0
  4. data/.rubocop.yml +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +7 -0
  7. data/Guardfile +43 -0
  8. data/LICENSE +20 -0
  9. data/README.md +28 -0
  10. data/Rakefile +6 -0
  11. data/bin/lb-project +29 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/mutant.yml +3 -0
  16. data/config/reek.yml +103 -0
  17. data/config/rubocop.yml +10 -0
  18. data/config/yardstick.yml +2 -0
  19. data/lb-project.gemspec +42 -0
  20. data/lib/lb/project/app.rb +9 -0
  21. data/lib/lb/project/config.rb +35 -0
  22. data/lib/lb/project/page.rb +19 -0
  23. data/lib/lb/project/registry/registration.rb +73 -0
  24. data/lib/lb/project/registry.rb +58 -0
  25. data/lib/lb/project/render.rb +28 -0
  26. data/lib/lb/project/route.rb +15 -0
  27. data/lib/lb/project/site.rb +41 -0
  28. data/lib/lb/project/types.rb +10 -0
  29. data/lib/lb/project/version.rb +8 -0
  30. data/lib/lb/project/view.rb +19 -0
  31. data/lib/lb/project.rb +159 -0
  32. data/lib/lb-project.rb +5 -0
  33. data/rakelib/ci.rake +24 -0
  34. data/spec/fixtures/config/application.yml +10 -0
  35. data/spec/fixtures/config/lb-project.yml +3 -0
  36. data/spec/fixtures/config.ru +9 -0
  37. data/spec/fixtures/docs/assets/javascripts/main.bundle.js +0 -0
  38. data/spec/fixtures/docs/assets/stylesheets/main.bundle.css +0 -0
  39. data/spec/fixtures/lib/example/app.rb +14 -0
  40. data/spec/fixtures/lib/example/page/index.rb +13 -0
  41. data/spec/fixtures/lib/example/page.rb +8 -0
  42. data/spec/fixtures/lib/example.rb +15 -0
  43. data/spec/fixtures/locales/en.yml +7 -0
  44. data/spec/fixtures/templates/index.html.slim +7 -0
  45. data/spec/fixtures/templates/layouts/main.html.slim +13 -0
  46. data/spec/fixtures/webpack-assets.json +1 -0
  47. data/spec/spec_helper.rb +31 -0
  48. data/spec/support/helper.rb +5 -0
  49. data/spec/unit/lb/project/class_methods/config_spec.rb +57 -0
  50. data/spec/unit/lb/project/class_methods/development_quest_spec.rb +39 -0
  51. data/spec/unit/lb/project/class_methods/logger_spec.rb +25 -0
  52. data/spec/unit/lb/project/class_methods/rack_env_spec.rb +39 -0
  53. data/spec/unit/lb/project/class_methods/root_for_spec.rb +28 -0
  54. data/spec/unit/lb/project/class_methods/root_spec.rb +31 -0
  55. data/spec/unit/lb/project/class_methods/setup_spec.rb +23 -0
  56. metadata +373 -0
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Version
6
+ VERSION = '0.0.1'
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LB
4
+ module Project
5
+ # Base view
6
+ class View < Dry::View::Controller
7
+ extend LB::Project::Registry::Registration[:view]
8
+
9
+ def self.setup(view)
10
+ view.setting :paths, [LB::Project.template_path]
11
+ view.setting :layout, 'main'
12
+ end
13
+
14
+ def view_locals(options)
15
+ options
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/lb/project.rb ADDED
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ # Web
7
+ require 'roda'
8
+ require 'roda/plugins/public'
9
+
10
+ # r18n
11
+ require 'r18n-core'
12
+
13
+ # Dry
14
+ require 'dry-types'
15
+ require 'dry-struct'
16
+ require 'dry-view'
17
+ require 'dry-initializer'
18
+
19
+ # Version
20
+ require 'lb/project/version'
21
+
22
+ # Custom Types
23
+ require 'lb/project/types'
24
+
25
+ # Config
26
+ require 'lb/project/config'
27
+
28
+ # LB namespace
29
+ module LB
30
+ # Project
31
+ module Project
32
+ CONFIG_NAME = 'application'
33
+ DEFAULT_RACK_ENV = 'development'
34
+
35
+ # Setup
36
+ #
37
+ # @param [File] root Path to project root
38
+ #
39
+ # @return [self]
40
+ #
41
+ # @api private
42
+ #
43
+ def self.setup(root)
44
+ @root = root
45
+
46
+ self
47
+ end
48
+
49
+ # Get root path
50
+ #
51
+ # @return [dir_name]
52
+ #
53
+ # @api private
54
+ #
55
+ def self.root
56
+ @root
57
+ end
58
+
59
+ # Get root path for file
60
+ #
61
+ # @param [File] file The file to get the root path from
62
+ # @param [File] depth The depth of the given file relative from the root
63
+ # directory
64
+ #
65
+ # @return [dir_name]
66
+ #
67
+ # @api private
68
+ #
69
+ def self.root_for(file, depth = 2)
70
+ path = File.expand_path(file)
71
+ depth.times { path = File.dirname(path) }
72
+ path
73
+ end
74
+
75
+ # Get template path
76
+ #
77
+ # @return [dir_name]
78
+ #
79
+ # @api private
80
+ #
81
+ def self.template_path
82
+ File.join(root, config.template_path)
83
+ end
84
+
85
+ # Get public path
86
+ #
87
+ # @return [dir_name]
88
+ #
89
+ # @api private
90
+ #
91
+ def self.public_path
92
+ File.join(root, config.public_path)
93
+ end
94
+
95
+ # Get main configuration
96
+ #
97
+ # @return [Config]
98
+ #
99
+ # @api private
100
+ #
101
+ def self.config
102
+ @config ||= Config.load(root, CONFIG_NAME, rack_env)
103
+ end
104
+
105
+ # Get RACK_ENV
106
+ #
107
+ # @return [String]
108
+ #
109
+ # @api private
110
+ #
111
+ def self.rack_env
112
+ @rack_env ||= ENV.fetch('RACK_ENV', DEFAULT_RACK_ENV)
113
+ end
114
+
115
+ # Check if rack_env is 'development'
116
+ #
117
+ # @return [Boolean]
118
+ #
119
+ # @api private
120
+ #
121
+ def self.development?
122
+ DEFAULT_RACK_ENV.eql? rack_env
123
+ end
124
+
125
+ def self.t(*params)
126
+ R18n.t(*params)
127
+ end
128
+
129
+ def self.logger
130
+ @logger ||= create_logger
131
+ end
132
+
133
+ def self.create_logger
134
+ logger = Logger.new(STDOUT)
135
+ logger.level = Logger::INFO
136
+ logger
137
+ end
138
+
139
+ private_class_method :create_logger
140
+ end
141
+ end
142
+
143
+ # Site
144
+ require 'lb/project/site'
145
+
146
+ # Routing
147
+ require 'lb/project/route'
148
+ require 'lb/project/app'
149
+
150
+ # Registry
151
+ require 'lb/project/registry'
152
+ require 'lb/project/registry/registration'
153
+
154
+ # Views
155
+ require 'lb/project/view'
156
+ require 'lb/project/page'
157
+
158
+ # Render
159
+ require 'lb/project/render'
data/lib/lb-project.rb ADDED
@@ -0,0 +1,5 @@
1
+ # rubocop:disable Naming/FileName
2
+ # frozen_string_literal: true
3
+
4
+ require 'lb/project'
5
+ # rubocop:enable Naming/FileName
data/rakelib/ci.rake ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Remove existing same-named tasks
4
+ %w[ci ci:metrics].each do |task|
5
+ klass = Rake::Task
6
+ klass[task].clear if klass.task_defined?(task)
7
+ end
8
+
9
+ desc 'Run all specs, metrics and mutant'
10
+ task ci: %w[ci:metrics metrics:mutant]
11
+
12
+ namespace :ci do
13
+ tasks = %w[
14
+ metrics:coverage
15
+ metrics:yardstick:verify
16
+ metrics:rubocop
17
+ metrics:flog
18
+ metrics:flay
19
+ spec:integration
20
+ ]
21
+
22
+ desc 'Run metrics (except mutant)'
23
+ task metrics: tasks
24
+ end
@@ -0,0 +1,10 @@
1
+ development: &base
2
+ base_path : ''
3
+ image_base_path: 'assets/images'
4
+ public_path: 'docs'
5
+ template_path: 'templates'
6
+ test:
7
+ <<: *base
8
+ production:
9
+ <<: *base
10
+ public_path: 'htdocs'
@@ -0,0 +1,3 @@
1
+ ---
2
+ namespace: example
3
+
@@ -0,0 +1,9 @@
1
+ #\ -p 3000 -P invalid_public_path_to_disable_shotguns_static_route
2
+ # frozen_string_literal: true
3
+
4
+ root = File.dirname(File.expand_path(__FILE__))
5
+ $LOAD_PATH << File.join(root, 'lib')
6
+
7
+ require 'example'
8
+
9
+ run Example::App.freeze.app
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Example
4
+ # Main routing entry point
5
+ class App < LB::Project::App
6
+ LB::Project::Route.setup(self)
7
+
8
+ route do |r|
9
+ r.i18n_set_locale_from(:http)
10
+
11
+ r.public
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Example
4
+ class Page
5
+ # The index page
6
+ class Index < self
7
+ setting :template, 'index'
8
+
9
+ register_page_as :index
10
+ register_view_as :index
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Example
4
+ # Base page
5
+ class Page < LB::Project::Page
6
+ LB::Project::View.setup(self)
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Slim
4
+ require 'slim'
5
+
6
+ require 'lb-project'
7
+
8
+ # Example project
9
+ module Example
10
+ LB::Project.setup(LB::Project.root_for(__FILE__))
11
+ end
12
+
13
+ require 'example/app'
14
+ require 'example/page'
15
+ require 'example/page/index'
@@ -0,0 +1,7 @@
1
+ site:
2
+ title: lb-rb.org
3
+ logo: Logo
4
+
5
+ page:
6
+ index:
7
+ title: lb-rb.org
@@ -0,0 +1,7 @@
1
+ body
2
+ h1 lb-rb.org
3
+
4
+ #content
5
+ p
6
+ a href='https://github.com/lb-rb'
7
+ | Visit us at GitHub
@@ -0,0 +1,13 @@
1
+ doctype html
2
+ html
3
+ head
4
+ meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"
5
+ meta charset="utf-8"
6
+ meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"
7
+
8
+ title = "#{_context.page.title} - #{site.t.site.title}"
9
+
10
+ link href="#{site.css_for('main')}" rel='stylesheet' type='text/css'
11
+ script src="#{site.js_for('main')}"
12
+
13
+ == yield
@@ -0,0 +1 @@
1
+ {"main":{"js":"assets/javascripts/main.bundle.js","css":"assets/stylesheets/main.bundle.css"}}
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ if ENV['COVERAGE'] == 'true'
5
+ require 'simplecov'
6
+
7
+ SimpleCov.start do
8
+ command_name 'spec:unit'
9
+
10
+ add_filter 'config'
11
+ add_filter 'spec'
12
+
13
+ minimum_coverage 100
14
+ end
15
+ end
16
+
17
+ $LOAD_PATH << 'lib'
18
+
19
+ require 'lb-project'
20
+
21
+ require 'devtools/spec_helper'
22
+
23
+ # require spec support files and shared behavior
24
+ Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each do |file|
25
+ require file
26
+ end
27
+
28
+ RSpec.configure do |config|
29
+ config.include(SpecHelper)
30
+ config.mock_framework = :rspec
31
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Spec Helper
4
+ module SpecHelper
5
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.config' do
6
+ subject { object.config }
7
+
8
+ let(:object) { described_class }
9
+
10
+ let(:default_hash) do
11
+ {
12
+ base_path: '',
13
+ image_base_path: 'assets/images',
14
+ public_path: 'docs',
15
+ template_path: 'templates'
16
+ }
17
+ end
18
+
19
+ let(:default) { LB::Project::Config.new(default_hash) }
20
+
21
+ let(:env) { 'RACK_ENV' }
22
+
23
+ before(:each) do
24
+ root = LB::Project.root_for(__FILE__, 6)
25
+ LB::Project.setup(File.join(root, 'spec/fixtures'))
26
+ end
27
+
28
+ after(:each) do
29
+ object.remove_instance_variable(:@rack_env)
30
+ object.remove_instance_variable(:@config)
31
+ object.remove_instance_variable(:@root)
32
+ end
33
+
34
+ context 'without RACK_ENV' do
35
+ it 'should return default config' do
36
+ expect(subject).to eql(default)
37
+ end
38
+ end
39
+
40
+ context 'with RACK_ENV=production' do
41
+ let(:production_hash) { default_hash.merge(public_path: 'htdocs') }
42
+ let(:production) { LB::Project::Config.new(production_hash) }
43
+ let(:rack_env) { 'production' }
44
+
45
+ before(:each) do
46
+ ENV[env] = rack_env
47
+ end
48
+
49
+ after(:each) do
50
+ ENV.delete(env)
51
+ end
52
+
53
+ it 'should return production config' do
54
+ expect(subject).to eql(production)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.development?' do
6
+ subject { object.development? }
7
+
8
+ let(:object) { described_class }
9
+
10
+ let(:default) { 'development' }
11
+
12
+ let(:env) { 'RACK_ENV' }
13
+
14
+ after(:each) do
15
+ object.remove_instance_variable(:@rack_env)
16
+ end
17
+
18
+ context 'without RACK_ENV' do
19
+ it 'should return true' do
20
+ expect(subject).to be true
21
+ end
22
+ end
23
+
24
+ context 'with RACK_ENV=production' do
25
+ let(:rack_env) { 'production' }
26
+
27
+ before(:each) do
28
+ ENV[env] = rack_env
29
+ end
30
+
31
+ after(:each) do
32
+ ENV.delete(env)
33
+ end
34
+
35
+ it 'should return false' do
36
+ expect(subject).to be false
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.logger' do
6
+ subject { object.logger }
7
+
8
+ let(:object) { described_class }
9
+
10
+ let(:expected_level) { Logger::INFO }
11
+
12
+ let(:expected_type) { Logger }
13
+
14
+ after(:each) do
15
+ object.remove_instance_variable(:@logger)
16
+ end
17
+
18
+ it 'should return logger of type Logger' do
19
+ expect(subject.class).to be(expected_type)
20
+ end
21
+
22
+ it 'should set log level to info' do
23
+ expect(subject.level).to be(expected_level)
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.rack_env' do
6
+ subject { object.rack_env }
7
+
8
+ let(:object) { described_class }
9
+
10
+ let(:default) { 'development' }
11
+
12
+ let(:env) { 'RACK_ENV' }
13
+
14
+ after(:each) do
15
+ object.remove_instance_variable(:@rack_env)
16
+ end
17
+
18
+ context 'without RACK_ENV' do
19
+ it 'should return default RACK_ENV' do
20
+ expect(subject).to eql(default)
21
+ end
22
+ end
23
+
24
+ context 'with RACK_ENV=production' do
25
+ let(:rack_env) { 'production' }
26
+
27
+ before(:each) do
28
+ ENV[env] = rack_env
29
+ end
30
+
31
+ after(:each) do
32
+ ENV.delete(env)
33
+ end
34
+
35
+ it 'should return production' do
36
+ expect(subject).to eql(rack_env)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.root_for' do
6
+ subject { object.root_for(*args) }
7
+
8
+ let(:args) { [file] }
9
+ let(:object) { described_class }
10
+ let(:file) { __FILE__ }
11
+
12
+ let(:expected) { File.dirname(File.dirname(File.expand_path(file))) }
13
+
14
+ it 'should equal the absolute parent path (two directory levels up)' do
15
+ expect(subject).to eql(expected)
16
+ end
17
+
18
+ context 'with depth of 3' do
19
+ let(:args) { [file, 3] }
20
+ let(:expected) do
21
+ File.dirname(File.dirname(File.dirname(File.expand_path(file))))
22
+ end
23
+
24
+ it 'should equal the absolute parent path (two directory levels up)' do
25
+ expect(subject).to eql(expected)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.root' do
6
+ subject { object.root }
7
+
8
+ let(:object) { described_class }
9
+
10
+ context 'without setup' do
11
+ it 'should return nil' do
12
+ expect(subject).to be_nil
13
+ end
14
+ end
15
+
16
+ context 'without setup' do
17
+ let(:root) { double(:root) }
18
+
19
+ before(:each) do
20
+ object.setup(root)
21
+ end
22
+
23
+ after(:each) do
24
+ object.remove_instance_variable(:@root)
25
+ end
26
+
27
+ it 'should return nil' do
28
+ expect(subject).to be(root)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe LB::Project, '.setup' do
6
+ subject { object.setup(root) }
7
+
8
+ let(:root) { double(:root) }
9
+ let(:object) { described_class }
10
+
11
+ after(:each) do
12
+ object.remove_instance_variable(:@root)
13
+ end
14
+
15
+ it 'should return self' do
16
+ expect(subject).to eql(object)
17
+ end
18
+
19
+ it 'should set root' do
20
+ subject
21
+ expect(object.root).to be(root)
22
+ end
23
+ end