k_builder 0.0.1 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d63754fbda587b7ea17d7ae17d4fb33029fac853280ce5125bfb1d7924c4ddfc
4
- data.tar.gz: 62d174cd9cf2b5ad60a43319875efffc6845a409ea1067b4cb01d916f69456cf
3
+ metadata.gz: ff2053d7113bdfdf11d6289f81220840a742362b20a5ee4283a995eff8010101
4
+ data.tar.gz: f3a70c18493de81b6b5eebaf90555ce222cb2144825aeb154265f4704a9cd43e
5
5
  SHA512:
6
- metadata.gz: 53b98c935cb446629725ccb9a4bd4fa6babe87e985e7886ab2308592cb5413604063cb54eee5f439dfe79263b3d73d03c32c94cbe9ccb89eaf0599b1c655e9ea
7
- data.tar.gz: 985ad06c8e9a92f5e79eab2167b35cebee0940ae87bd9044e3de466c09786364444cbffafe7441bef59f8d031186106ffc317d9ddc91dc6c9288066db670f548
6
+ metadata.gz: 20f67a1a1409f111b4d76c6bd45858342d6d04c82e60f6b5d646e07eea64ff2a0630a290ef94832e09181528d1d86143b0635717a33f06bcc84d12c55d93d8fb
7
+ data.tar.gz: 6527ac296eb3f43f89bfad8028084adbe89412ebb3547143a8c0a6771e1af95ae06805d79ce696f428ac5e955b444e96dbb0dec399b12d2e0c525c11956a23b5
data/.rubocop.yml CHANGED
@@ -60,6 +60,9 @@ Naming/MemoizedInstanceVariableName:
60
60
  Naming/VariableNumber:
61
61
  Exclude:
62
62
  - "**/spec/**/*"
63
+ Naming/AccessorMethodName:
64
+ Exclude:
65
+ - "**/*builder*.rb"
63
66
  Style/EmptyMethod:
64
67
  Exclude:
65
68
  - "**/spec/**/*"
data/Guardfile ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard :bundler, cmd: 'bundle install' do
4
+ watch('Gemfile')
5
+ watch('k_builder.gemspec')
6
+ end
7
+
8
+ group :green_pass_then_cop, halt_on_fail: true do
9
+ guard :rspec, cmd: 'bundle exec rspec -f doc' do
10
+ require 'guard/rspec/dsl'
11
+ dsl = Guard::RSpec::Dsl.new(self)
12
+
13
+ # RSpec files
14
+ rspec = dsl.rspec
15
+ watch(rspec.spec_helper) { rspec.spec_dir }
16
+ watch(rspec.spec_support) { rspec.spec_dir }
17
+ watch(rspec.spec_files)
18
+
19
+ # Ruby files
20
+ ruby = dsl.ruby
21
+ dsl.watch_spec_files_for(ruby.lib_files)
22
+ watch(%r{^lib/k_builder/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
23
+ watch(%r{^lib/k_builder/commands/(.+)\.rb$}) { |m| "spec/unit/commands/#{m[1]}_spec.rb" }
24
+ end
25
+
26
+ guard :rubocop, all_on_start: false, cli: ['--format', 'clang'] do
27
+ watch(/{.+\.rb$/)
28
+ watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
29
+ end
30
+ end
data/README.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  > K Builder provides various fluent builders for initializing applications with different language requirements
4
4
 
5
+ ## ToDo
6
+
7
+ - BuildWatcher (as a builder)
8
+ - AppBuilder
9
+ - BaseBuilder
10
+ - WebBuilder
11
+ - PackageBuilder
12
+ - Webpack5Builder
13
+ - ReactBuilder
14
+ - SlideDeckBuilder
15
+ - JavscriptBuilder
16
+ - SolutionBuilder
17
+ - DotnetBuilder
18
+ - C#Console
19
+ - C#Mvc
20
+ - RubyBuilder
21
+ - RubyGem
22
+ - RailsApp
23
+ - PythonBuilder
24
+ - DddBuilder
25
+ - DddGenerator
26
+
27
+
5
28
  ## Installation
6
29
 
7
30
  Add this line to your application's Gemfile:
@@ -26,16 +49,23 @@ gem install k_builder
26
49
 
27
50
  ### Main Story
28
51
 
29
-
52
+ As a Polyglot Developer, I want to be up and running in any development language with consistency, so I am productive and using best practices
30
53
 
31
54
  See all [stories](./STORIES.md)
32
55
 
33
-
34
56
  ## Usage
35
57
 
36
58
  See all [usage examples](./USAGE.md)
37
59
 
60
+ ### Basic Example
38
61
 
62
+ #### Basic example
63
+
64
+ Description for a basic example to be featured in the main README.MD file
65
+
66
+ ```ruby
67
+ class SomeRuby; end
68
+ ```
39
69
 
40
70
  ## Development
41
71
 
@@ -45,7 +75,7 @@ Checkout the repo
45
75
  git clone klueless-io/k_builder
46
76
  ```
47
77
 
48
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
78
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
49
79
 
50
80
  You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
81
 
data/STORIES.md CHANGED
@@ -8,26 +8,21 @@ As a Polyglot Developer, I want to be up and running in any development language
8
8
 
9
9
  ### Stories next on list
10
10
 
11
- As a Developer, I can DO_SOMETHING, so that I QUALITY_OF_LIFE
12
-
13
- - Subtask
11
+ As a Polyglot Developer, I want to be up and running in any development language with consistency, so I am productive and using best practices [EPIC]
14
12
 
15
13
  ### Tasks next on list
16
14
 
17
- Setup RubyGems and RubyDoc
18
-
19
- - Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_builder)
20
- - Attach documentation to [rubydoc.info](https://rubydoc.info/github/to-do-/k_builder/master)
21
-
22
- Setup GitHub Action (test and lint)
23
-
24
- - Setup Rspec action
25
- - Setup RuboCop action
15
+ BaseBuilder
26
16
 
27
17
  ## Stories and tasks
28
18
 
29
19
  ### Tasks - completed
30
20
 
21
+ Setup RubyGems and RubyDoc
22
+
23
+ - Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_builder)
24
+ - Attach documentation to [rubydoc.info](https://rubydoc.info/github/to-do-/k_builder/master)
25
+
31
26
  Setup project management, requirement and SCRUM documents
32
27
 
33
28
  - Setup readme file
@@ -35,6 +30,11 @@ Setup project management, requirement and SCRUM documents
35
30
  - Setup a project backlog
36
31
  - Setup an examples/usage document
37
32
 
33
+ Setup GitHub Action (test and lint)
34
+
35
+ - Setup Rspec action
36
+ - Setup RuboCop action
37
+
38
38
  Setup new Ruby GEM
39
39
 
40
40
  - Build out a standard GEM structure
data/k_builder.gemspec CHANGED
@@ -38,5 +38,6 @@ Gem::Specification.new do |spec|
38
38
  spec.require_paths = ['lib']
39
39
  # spec.extensions = ['ext/k_builder/extconf.rb']
40
40
 
41
+ spec.add_dependency 'handlebars-helpers', '~> 0'
41
42
  # spec.add_dependency 'tty-box', '~> 0.5.0'
42
43
  end
data/lib/k_builder.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'k_builder/version'
4
+ require 'k_builder/configuration'
5
+ require 'k_builder/base_builder'
6
+ require 'k_builder/builder'
7
+
8
+ require 'handlebars/helpers/template'
4
9
 
5
10
  module KBuilder
6
11
  # raise KBuilder::Error, 'Sample message'
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBuilder
4
+ # Base builder defines builder methods, build method and configuration
5
+ #
6
+ # Convention: Setter methods (are Fluent) and use the prefix set_
7
+ # Getter methods (are NOT fluent) and return the stored value
8
+ # Setter methods (are NOT fluent) can be created as needed
9
+ # these methods would not be prefixed with the set_
10
+ class BaseBuilder
11
+ attr_reader :hash
12
+
13
+ # Factory method that provides a builder for a specified structure
14
+ # runs through a configuration block and then builds the final structure
15
+ #
16
+ # @return [type=Object] data structure
17
+ def self.build
18
+ init.build
19
+ end
20
+
21
+ # Create and initialize the builder.
22
+ #
23
+ # Initialization can be done via any of these three sequential steps.
24
+ # - Configuration hash
25
+ # - After new event
26
+ # - Configuration block (lambda)
27
+ #
28
+ # @return [Builder] Returns the builder via fluent interface
29
+ def self.init(configuration = nil)
30
+ builder = new(configuration)
31
+
32
+ builder.after_new
33
+
34
+ yield(builder) if block_given?
35
+
36
+ builder
37
+ end
38
+
39
+ # Use after_new to massage hash values that come in via
40
+ # configuration into more complex values
41
+ #
42
+ # Abstract method
43
+ def after_new; end
44
+
45
+ # assigns a builder hash and defines builder methods
46
+ def initialize(configuration = nil)
47
+ @hash = {}
48
+
49
+ unless configuration.nil?
50
+ raise KBuilder::StandardError, 'Unknown configuration object' unless configuration.is_a?(Hash)
51
+
52
+ hash.merge!(configuration)
53
+ end
54
+
55
+ define_builder_setter_methods
56
+ end
57
+
58
+ # Return an array of symbols to represent the fluent
59
+ # setter methods that you want on your builder.
60
+ #
61
+ # Abstract method
62
+ def builder_setter_methods
63
+ raise NotImplementedError
64
+ end
65
+
66
+ # @return [Hash/StrongType] Returns data object, can be a hash
67
+ # or strong typed object that you
68
+ # have wrapped around the hash
69
+ def build
70
+ hash
71
+ end
72
+
73
+ # builds a nested structure by either builder block or hash
74
+ # @param data_structure [type=DataStructure]
75
+ # @param builder [type=Builder]
76
+ # @param attributes [type=Hash|DataStructure instance]
77
+ # @param &block
78
+ #
79
+ # @return [type=Hash]
80
+ def build_nested(data_structure, builder, attributes = {}, &block)
81
+ if block_given?
82
+ builder.build(&block).to_h
83
+ else
84
+ build_hash(data_structure, attributes)
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ #
91
+ # @param data_structure [type=DataStructure]
92
+ # @param attributes [type=Hash, DataStructure]
93
+ #
94
+ # @return [type=Hash]
95
+ def build_hash(data_structure, attributes)
96
+ if attributes.is_a?(data_structure)
97
+ attributes.to_h
98
+ else
99
+ data_structure.new(attributes).to_h
100
+ end
101
+ end
102
+
103
+ # Defines all of the necessary builder setter methods
104
+ #
105
+ # @return [Builder] Returns the builder via fluent interface
106
+ def define_builder_setter_methods
107
+ builder_setter_methods.each { |method| define_builder_method(method) }
108
+ self
109
+ end
110
+
111
+ # Defines a method using the convention set_[method_name]
112
+ #
113
+ # Convention: Setter methods (are Fluent) and use the prefix set_
114
+ # Getter methods (are NOT fluent) and return the stored value
115
+ #
116
+ # @return [Builder] Returns the builder via fluent interface
117
+ def define_builder_method(method_name)
118
+ self.class.send(:define_method, "set_#{method_name}") do |value|
119
+ @hash[method_name.to_s] = value
120
+ self
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBuilder
4
+ # Base builder defines builder methods, build method and configuration
5
+ class Builder < KBuilder::BaseBuilder
6
+ # builder_setter_methods = %w[].freeze
7
+ # target_folder
8
+ # template_folder
9
+ # global_template_folder
10
+
11
+ def initialize(configuration = nil)
12
+ configuration = KBuilder.configuration.to_hash if configuration.nil?
13
+
14
+ super(configuration)
15
+ end
16
+
17
+ # rubocop:disable Metrics/AbcSize
18
+ def after_new
19
+ # ensure that any configured folders are expanded
20
+ self.target_folder = hash['target_folder'] unless hash['target_folder'].nil?
21
+ self.template_folder = hash['template_folder'] unless hash['template_folder'].nil?
22
+ self.global_template_folder = hash['global_template_folder'] unless hash['global_template_folder'].nil?
23
+ end
24
+ # rubocop:enable Metrics/AbcSize
25
+
26
+ # Return an array of symbols to represent the fluent setter methods in this builder.
27
+ def builder_setter_methods
28
+ # Currently I have manually created my settings because I needed custom
29
+ # logic in the settings to handle path expansion
30
+ []
31
+ end
32
+
33
+ # def build
34
+ # # SomeDryStruct.new(hash)
35
+ # end
36
+
37
+ # ----------------------------------------------------------------------
38
+ # Fluent interface
39
+ # ----------------------------------------------------------------------
40
+
41
+ # Add a file to the target location
42
+ #
43
+ # @param [String] file The file name with or without relative path, eg. my_file.json or src/my_file.json
44
+ # @option opts [String] :content Supply the content that you want to write to the file
45
+ # @option opts [String] :template Supply the template that you want to write to the file, template will be processed ('nobody') From address
46
+ # @option opts [String] :content_file File with content, file location is based on where the program is running
47
+ # @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
48
+ #
49
+ # Extra options will be used as data for templates, e.g
50
+ # @option opts [String] :to Recipient email
51
+ # @option opts [String] :body The email's body
52
+ def add_file(file, **opts)
53
+ full_file = target_file(file)
54
+
55
+ FileUtils.mkdir_p(File.dirname(full_file))
56
+
57
+ content = process_any_content(**opts)
58
+
59
+ File.write(full_file, content)
60
+
61
+ # Prettier needs to work with the original file name
62
+ run_prettier file if opts.key?(:pretty)
63
+
64
+ self
65
+ end
66
+
67
+ # ----------------------------------------------------------------------
68
+ # Attributes: Think getter/setter
69
+ #
70
+ # The following getter/setters can be referenced both inside and outside
71
+ # of the fluent builder fluent API. They do not implement the fluent
72
+ # interface unless prefixed by set_.
73
+ #
74
+ # set_: Only setters with the prefix _set are considered fluent.
75
+ # ----------------------------------------------------------------------
76
+
77
+ # Target folder
78
+ # ----------------------------------------------------------------------
79
+
80
+ # Fluent setter for target folder
81
+ def set_target_folder(value)
82
+ self.target_folder = value
83
+
84
+ self
85
+ end
86
+
87
+ # Setter for target folder
88
+ def target_folder=(value)
89
+ hash['target_folder'] = File.expand_path(value)
90
+ end
91
+
92
+ # Getter for target folder
93
+ def target_folder
94
+ hash['target_folder']
95
+ end
96
+
97
+ # Template folder
98
+ # ----------------------------------------------------------------------
99
+
100
+ # Fluent setter for template folder
101
+ def set_template_folder(value)
102
+ self.template_folder = value
103
+
104
+ self
105
+ end
106
+
107
+ # Setter for template folder
108
+ def template_folder=(value)
109
+ hash['template_folder'] = File.expand_path(value)
110
+ end
111
+
112
+ # Getter for template folder
113
+ def template_folder
114
+ hash['template_folder']
115
+ end
116
+
117
+ # Global Target folder
118
+ # ----------------------------------------------------------------------
119
+
120
+ # Fluent setter for global template folder
121
+ def set_global_template_folder(value)
122
+ self.global_template_folder = value
123
+
124
+ self
125
+ end
126
+
127
+ # Setter for global template folder
128
+ def global_template_folder=(value)
129
+ hash['global_template_folder'] = File.expand_path(value)
130
+ end
131
+
132
+ # Setter for global template folder
133
+ def global_template_folder
134
+ hash['global_template_folder']
135
+ end
136
+
137
+ # Internal Actions are considered helpers for the builder, they do
138
+ # something useful, but they do not tend to implement fluent interfaces.
139
+ #
140
+ # They some times do actions, they sometimes return information.
141
+ #
142
+ # NOTE: [SRP] - These methods should probably be converted into objects
143
+ # ----------------------------------------------------------------------
144
+
145
+ # Gets a target_file relative to target folder
146
+ def target_file(file)
147
+ File.join(target_folder, file)
148
+ end
149
+
150
+ # Gets a template_file relative to the template folder
151
+ def template_file(file)
152
+ File.join(template_folder, file)
153
+ end
154
+
155
+ # Gets a global_template_file relative to the global template folder
156
+ def global_template_file(file)
157
+ File.join(global_template_folder, file)
158
+ end
159
+
160
+ # Gets a template_file relative to the template folder, looks first in
161
+ # local template folder and if not found, looks in global template folder
162
+ def find_template_file(file)
163
+ full_file = template_file(file)
164
+ return full_file if File.exist?(full_file)
165
+
166
+ full_file = global_template_file(file)
167
+ return full_file if File.exist?(full_file)
168
+
169
+ # File not found
170
+ nil
171
+ end
172
+
173
+ # Use content from a a selection of content sources
174
+ #
175
+ # @option opts [String] :content Just pass through the :content as is.
176
+ # @option opts [String] :content_file Read content from the :content_file
177
+ #
178
+ # Future options
179
+ # @option opts [String] :content_loren [TODO]Create Loren Ipsum text as a :content_loren count of words
180
+ # @option opts [String] :content_url Read content from the :content_url
181
+ #
182
+ # @return Returns some content
183
+ def use_content(**opts)
184
+ return opts[:content] unless opts[:content].nil?
185
+
186
+ return unless opts[:content_file]
187
+
188
+ cf = opts[:content_file]
189
+
190
+ return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf)
191
+
192
+ File.read(cf)
193
+ end
194
+
195
+ # Use template from a a selection of template sources
196
+ #
197
+ # @option opts [String] :template Just pass through the :template as is.
198
+ # @option opts [String] :template_file Read template from the :template_file
199
+ #
200
+ # @return Returns some template
201
+ def use_template(**opts)
202
+ return opts[:template] unless opts[:template].nil?
203
+
204
+ return unless opts[:template_file]
205
+
206
+ tf = find_template_file(opts[:template_file])
207
+
208
+ return "template not found: #{opts[:template_file]}" if tf.nil?
209
+
210
+ File.read(tf)
211
+ end
212
+
213
+ # Process content will take any one of the following
214
+ # - Raw content
215
+ # - File based content
216
+ # - Raw template (translated via handlebars)
217
+ # - File base template (translated via handlebars)
218
+ #
219
+ # Process any of the above inputs to create final content output
220
+ #
221
+ # @option opts [String] :content Supply the content that you want to write to the file
222
+ # @option opts [String] :template Supply the template that you want to write to the file, template will be transformed using handlebars
223
+ # @option opts [String] :content_file File with content, file location is based on where the program is running
224
+ # @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
225
+ def process_any_content(**opts)
226
+ raw_content = use_content(**opts)
227
+
228
+ return raw_content if raw_content
229
+
230
+ template_content = use_template(**opts)
231
+
232
+ Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
233
+ end
234
+
235
+ def run_prettier(file, log_level: :log)
236
+ # command = "prettier --check #{file} --write #{file}"
237
+ command = "prettier --loglevel #{log_level} --write #{file}"
238
+
239
+ run_command command
240
+ end
241
+
242
+ def run_command(command)
243
+ # Deep path create if needed
244
+ FileUtils.mkdir_p(target_folder)
245
+
246
+ build_command = "cd #{target_folder} && #{command}"
247
+
248
+ system(build_command)
249
+ end
250
+ alias rc run_command
251
+ end
252
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Attach configuration to the KBuilder module
4
+ module KBuilder
5
+ # Configuration for webpack5/builder
6
+ class << self
7
+ attr_writer :configuration
8
+ end
9
+
10
+ def self.configuration
11
+ @configuration ||= Configuration.new
12
+ end
13
+
14
+ def self.reset
15
+ @configuration = Configuration.new
16
+ end
17
+
18
+ def self.configure
19
+ yield(configuration)
20
+ end
21
+
22
+ # Configuration class
23
+ class Configuration
24
+ attr_accessor :target_folder
25
+ attr_accessor :template_folder
26
+ attr_accessor :global_template_folder
27
+
28
+ def initialize
29
+ @target_folder = Dir.getwd
30
+ @template_folder = File.join(Dir.getwd, '.templates')
31
+ @global_template_folder = nil
32
+ end
33
+
34
+ def debug
35
+ puts '-' * 120
36
+ puts 'kbuilder base configuration'
37
+ kv 'target_folder' , target_folder
38
+ kv 'template_folder' , template_folder
39
+ kv 'global_template_folder', global_template_folder
40
+ end
41
+
42
+ def to_hash
43
+ hash = {}
44
+ instance_variables.each { |var| hash[var.to_s.delete('@')] = instance_variable_get(var) }
45
+ hash
46
+ end
47
+
48
+ private
49
+
50
+ def kv(name, value)
51
+ puts "#{name.rjust(30)} : #{value}"
52
+ end
53
+ end
54
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KBuilder
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.14'
5
5
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: k_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-10 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: handlebars-helpers
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description: " K Builder provides various fluent builders for initializing applications
14
28
  with different language requirements\n"
15
29
  email:
@@ -24,6 +38,7 @@ files:
24
38
  - ".rubocop.yml"
25
39
  - CODE_OF_CONDUCT.md
26
40
  - Gemfile
41
+ - Guardfile
27
42
  - LICENSE.txt
28
43
  - README.md
29
44
  - Rakefile
@@ -38,6 +53,9 @@ files:
38
53
  - hooks/update-version
39
54
  - k_builder.gemspec
40
55
  - lib/k_builder.rb
56
+ - lib/k_builder/base_builder.rb
57
+ - lib/k_builder/builder.rb
58
+ - lib/k_builder/configuration.rb
41
59
  - lib/k_builder/version.rb
42
60
  homepage: http://appydave.com/gems/k-builder
43
61
  licenses: