k_builder 0.0.1 → 0.0.23
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 +4 -4
- data/.rubocop.yml +3 -0
- data/Guardfile +30 -0
- data/README.md +40 -4
- data/STORIES.md +13 -13
- data/USAGE.md +92 -7
- data/_out1.png +0 -0
- data/_out2.png +0 -0
- data/_out3.png +0 -0
- data/_out4.png +0 -0
- data/_out5.png +0 -0
- data/_usage_folder_after.png +0 -0
- data/_usage_folder_before.png +0 -0
- data/k_builder.gemspec +4 -2
- data/lib/k_builder.rb +6 -0
- data/lib/k_builder/base_builder.rb +131 -0
- data/lib/k_builder/base_configuration.rb +106 -0
- data/lib/k_builder/builder.rb +258 -0
- data/lib/k_builder/configuration.rb +43 -0
- data/lib/k_builder/version.rb +1 -1
- metadata +31 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e1de8ff91bc3e273459d6970c8c1c136184e9c0990b0645fa426888317640eb
|
|
4
|
+
data.tar.gz: b6a5856f4bbb628422968a80a212fc6fbb1515b19c2cc29160d9cf984faa2b40
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 62e85ea3f17a20cbc3bd180b74a057caab722d37de1bdb008353839f5f0159f564b69a4bcee9124857c7d24fe5b7b46afe967b86e52aaac7009960a663294886
|
|
7
|
+
data.tar.gz: 51a3c0374b57f0cfebc099df6d86c7657b50815185ea60f71e37cc9f27c5edf4afbb1933e727c1e68b81b179b079f7666c89a9273e971d7aa72fdb74e0411942
|
data/.rubocop.yml
CHANGED
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# K Builder
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> KBuilder provides various fluent builders and code generators for initializing applications with different language requirements
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -26,16 +26,52 @@ gem install k_builder
|
|
|
26
26
|
|
|
27
27
|
### Main Story
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
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
30
|
|
|
31
31
|
See all [stories](./STORIES.md)
|
|
32
32
|
|
|
33
|
-
|
|
34
33
|
## Usage
|
|
35
34
|
|
|
36
35
|
See all [usage examples](./USAGE.md)
|
|
37
36
|
|
|
37
|
+
### Basic Example
|
|
38
|
+
|
|
39
|
+
#### Configure and Run
|
|
40
|
+
|
|
41
|
+
Setup configuration for KBuilder
|
|
42
|
+
|
|
43
|
+
Generate two files:
|
|
38
44
|
|
|
45
|
+
1. main.rb is based on class.rb from app_template
|
|
46
|
+
2. configuration.log.txt is based on an inline template
|
|
47
|
+
|
|
48
|
+
Check out usage.md for more details
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
usecases_folder = File.join(Dir.getwd, 'spec', 'usecases')
|
|
52
|
+
|
|
53
|
+
KBuilder.configure do |config|
|
|
54
|
+
config.template_folder = File.join(usecases_folder, '.app_template')
|
|
55
|
+
config.global_template_folder = File.join(usecases_folder, '.global_template')
|
|
56
|
+
config.target_folder = File.join(usecases_folder, '.output')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
template = <<~TEXT
|
|
60
|
+
Configured Template Folder : {{a}}
|
|
61
|
+
Configured Global Template Folder : {{b}}
|
|
62
|
+
Configured Output Folder : {{c}}
|
|
63
|
+
TEXT
|
|
64
|
+
|
|
65
|
+
builder = KBuilder::Builder.init
|
|
66
|
+
|
|
67
|
+
builder.add_file('main.rb', template_file: 'class.rb', name: 'main').add_file(
|
|
68
|
+
'configuration.log.txt',
|
|
69
|
+
template: template,
|
|
70
|
+
a: builder.template_folder,
|
|
71
|
+
b: builder.global_template_folder,
|
|
72
|
+
c: builder.target_folder
|
|
73
|
+
)
|
|
74
|
+
```
|
|
39
75
|
|
|
40
76
|
## Development
|
|
41
77
|
|
|
@@ -45,7 +81,7 @@ Checkout the repo
|
|
|
45
81
|
git clone klueless-io/k_builder
|
|
46
82
|
```
|
|
47
83
|
|
|
48
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
|
84
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
|
49
85
|
|
|
50
86
|
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
51
87
|
|
data/STORIES.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# K Builder
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> KBuilder provides various fluent builders and code generators for initializing applications with different language requirements
|
|
4
4
|
|
|
5
5
|
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
|
|
6
6
|
|
|
@@ -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
|
|
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
|
-
|
|
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/USAGE.md
CHANGED
|
@@ -1,19 +1,104 @@
|
|
|
1
1
|
# K Builder
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> KBuilder provides various fluent builders and code generators for initializing applications with different language requirements
|
|
4
4
|
|
|
5
5
|
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
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
|
-
###
|
|
9
|
+
### Configure And Build
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Description for a simple example that shows up in the USAGE.MD
|
|
11
|
+
Print the configuration
|
|
14
12
|
|
|
15
13
|
```ruby
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
usecases_folder = File.join(Dir.getwd, 'spec', 'usecases')
|
|
15
|
+
|
|
16
|
+
KBuilder.configure do |config|
|
|
17
|
+
config.template_folder = File.join(usecases_folder, '.app_template')
|
|
18
|
+
config.global_template_folder = File.join(usecases_folder, '.global_template')
|
|
19
|
+
config.target_folder = File.join(usecases_folder, '.output')
|
|
18
20
|
end
|
|
21
|
+
|
|
22
|
+
puts JSON.pretty_generate(KBuilder.configuration.to_hash)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
{
|
|
27
|
+
"target_folder": "/Users/name/dev/kgems/k_builder/spec/usecases/.output",
|
|
28
|
+
"template_folder": "/Users/name/dev/kgems/k_builder/spec/usecases/.app_template",
|
|
29
|
+
"global_template_folder": "/Users/name/dev/kgems/k_builder/spec/usecases/.global_template"
|
|
30
|
+
}
|
|
19
31
|
```
|
|
32
|
+
|
|
33
|
+
#### Folder Structure (starting)
|
|
34
|
+
|
|
35
|
+
Example folder structure for this usecase before running the builder
|
|
36
|
+
|
|
37
|
+
> Note: app-templates will take preference over global templates
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
#### Run builder
|
|
42
|
+
|
|
43
|
+
This example builder will add 4 files into the output folder.
|
|
44
|
+
|
|
45
|
+
1. `main.rb` is based on `class.rb` from `app_template`
|
|
46
|
+
2. `person.rb` & `address.rb` are based on `model.rb` from `global_template`
|
|
47
|
+
3. `configuration.log.txt` is based on an inline template
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
template = <<~TEXT
|
|
51
|
+
Configured Template Folder : {{a}}
|
|
52
|
+
Configured Global Template Folder : {{b}}
|
|
53
|
+
Configured Output Folder : {{c}}
|
|
54
|
+
TEXT
|
|
55
|
+
|
|
56
|
+
builder = KBuilder::Builder.init
|
|
57
|
+
|
|
58
|
+
builder
|
|
59
|
+
.add_file('main.rb', template_file: 'class.rb', name: 'main')
|
|
60
|
+
.add_file('person.rb',
|
|
61
|
+
template_file: 'model.rb',
|
|
62
|
+
name: 'person',
|
|
63
|
+
fields: %i[first_name last_name])
|
|
64
|
+
.add_file('address.rb',
|
|
65
|
+
template_file: 'model.rb',
|
|
66
|
+
name: 'address',
|
|
67
|
+
fields: %i[street1 street2 post_code state])
|
|
68
|
+
.add_file('configuration.log.txt',
|
|
69
|
+
template: template,
|
|
70
|
+
a: builder.template_folder,
|
|
71
|
+
b: builder.global_template_folder,
|
|
72
|
+
c: builder.target_folder)
|
|
73
|
+
.add_file('css/index.css',
|
|
74
|
+
template: '{{#each colors}} .{{.}} { color: {{.}} } {{/each}}',
|
|
75
|
+
colors: ['red', 'blue', 'green'],
|
|
76
|
+
pretty: true)
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Folder Structure (after)
|
|
81
|
+
|
|
82
|
+
Folder structure after running the builder
|
|
83
|
+
|
|
84
|
+

|
|
85
|
+
|
|
86
|
+
#### main.rb
|
|
87
|
+
|
|
88
|
+

|
|
89
|
+
|
|
90
|
+
#### person.rb
|
|
91
|
+
|
|
92
|
+

|
|
93
|
+
|
|
94
|
+
#### address.rb
|
|
95
|
+
|
|
96
|
+

|
|
97
|
+
|
|
98
|
+
#### configuration.log.txt
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
#### css/index.css
|
|
103
|
+
|
|
104
|
+

|
data/_out1.png
ADDED
|
Binary file
|
data/_out2.png
ADDED
|
Binary file
|
data/_out3.png
ADDED
|
Binary file
|
data/_out4.png
ADDED
|
Binary file
|
data/_out5.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/k_builder.gemspec
CHANGED
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
spec.description = <<-TEXT
|
|
14
14
|
K Builder provides various fluent builders for initializing applications with different language requirements
|
|
15
15
|
TEXT
|
|
16
|
-
spec.homepage = 'http://appydave.com/gems/k-builder'
|
|
16
|
+
spec.homepage = 'http://appydave.com' # /gems/k-builder'
|
|
17
17
|
spec.license = 'MIT'
|
|
18
18
|
|
|
19
19
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
|
@@ -38,5 +38,7 @@ Gem::Specification.new do |spec|
|
|
|
38
38
|
spec.require_paths = ['lib']
|
|
39
39
|
# spec.extensions = ['ext/k_builder/extconf.rb']
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
spec.add_dependency 'handlebars-helpers', '~> 0'
|
|
42
|
+
# spec.add_dependency "anyway_config" , ">= 2.0.0"
|
|
43
|
+
# spec.add_dependency "config" , ">= 3.0.0"
|
|
42
44
|
end
|
data/lib/k_builder.rb
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'k_builder/version'
|
|
4
|
+
require 'k_builder/base_configuration'
|
|
5
|
+
require 'k_builder/configuration'
|
|
6
|
+
require 'k_builder/base_builder'
|
|
7
|
+
require 'k_builder/builder'
|
|
8
|
+
|
|
9
|
+
require 'handlebars/helpers/template'
|
|
4
10
|
|
|
5
11
|
module KBuilder
|
|
6
12
|
# raise KBuilder::Error, 'Sample message'
|
|
@@ -0,0 +1,131 @@
|
|
|
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
|
+
# TODO
|
|
74
|
+
# Support Nesting
|
|
75
|
+
# Support Generation fo the following
|
|
76
|
+
# - fluent set_
|
|
77
|
+
# - Support setter (non-fluent)
|
|
78
|
+
# - Support getter (non-fluent)
|
|
79
|
+
|
|
80
|
+
# # builds a nested structure by either builder block or hash
|
|
81
|
+
# # @param data_structure [type=DataStructure]
|
|
82
|
+
# # @param builder [type=Builder]
|
|
83
|
+
# # @param attributes [type=Hash|DataStructure instance]
|
|
84
|
+
# # @param &block
|
|
85
|
+
# #
|
|
86
|
+
# # @return [type=Hash]
|
|
87
|
+
# def build_nested(data_structure, builder, attributes = {}, &block)
|
|
88
|
+
# if block_given?
|
|
89
|
+
# builder.build(&block).to_h
|
|
90
|
+
# else
|
|
91
|
+
# build_hash(data_structure, attributes)
|
|
92
|
+
# end
|
|
93
|
+
# end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
# #
|
|
98
|
+
# # @param data_structure [type=DataStructure]
|
|
99
|
+
# # @param attributes [type=Hash, DataStructure]
|
|
100
|
+
# #
|
|
101
|
+
# # @return [type=Hash]
|
|
102
|
+
# def build_hash(data_structure, attributes)
|
|
103
|
+
# if attributes.is_a?(data_structure)
|
|
104
|
+
# attributes.to_h
|
|
105
|
+
# else
|
|
106
|
+
# data_structure.new(attributes).to_h
|
|
107
|
+
# end
|
|
108
|
+
# end
|
|
109
|
+
|
|
110
|
+
# Defines all of the necessary builder setter methods
|
|
111
|
+
#
|
|
112
|
+
# @return [Builder] Returns the builder via fluent interface
|
|
113
|
+
def define_builder_setter_methods
|
|
114
|
+
builder_setter_methods.each { |method| define_builder_method(method) }
|
|
115
|
+
self
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Defines a method using the convention set_[method_name]
|
|
119
|
+
#
|
|
120
|
+
# Convention: Setter methods (are Fluent) and use the prefix set_
|
|
121
|
+
# Getter methods (are NOT fluent) and return the stored value
|
|
122
|
+
#
|
|
123
|
+
# @return [Builder] Returns the builder via fluent interface
|
|
124
|
+
def define_builder_method(method_name)
|
|
125
|
+
self.class.send(:define_method, "set_#{method_name}") do |value|
|
|
126
|
+
@hash[method_name.to_s] = value
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBuilder
|
|
4
|
+
# Base configuration object for all k_builder* GEM
|
|
5
|
+
class BaseConfiguration
|
|
6
|
+
def to_hash
|
|
7
|
+
hash = {}
|
|
8
|
+
instance_variables.each { |var| hash[var.to_s.delete('@')] = instance_variable_get(var) }
|
|
9
|
+
hash
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def kv(name, value)
|
|
13
|
+
puts "#{name.rjust(30)} : #{value}"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# All of this code should be extracted into a module
|
|
17
|
+
#
|
|
18
|
+
# The module should then be extracted out into a GEM so that
|
|
19
|
+
# I can include it as needed. The GEM might be called
|
|
20
|
+
# (dynamic attributes) and would allow a regular class to act like an OpenStruct
|
|
21
|
+
# K-DSL uses data hash, while base configuration uses instance variables
|
|
22
|
+
|
|
23
|
+
def respond_to_missing?(name, *_args, &_block)
|
|
24
|
+
# puts 'respond_to_missing?'
|
|
25
|
+
# puts "respond_to_missing: #{name}"
|
|
26
|
+
n = name.to_s
|
|
27
|
+
n = n[0..-2] if n.end_with?('=')
|
|
28
|
+
|
|
29
|
+
if n.end_with?('?')
|
|
30
|
+
super
|
|
31
|
+
else
|
|
32
|
+
# This has not been fully tested
|
|
33
|
+
instance_variable_defined?("@#{n}") || super
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def method_missing(name, *args, &_block)
|
|
38
|
+
# puts "method_missing: #{name}"
|
|
39
|
+
# puts "args.length : #{args.length}"
|
|
40
|
+
|
|
41
|
+
add_getter_or_param_method(name)
|
|
42
|
+
add_setter_method(name)
|
|
43
|
+
|
|
44
|
+
send(name, args[0]) if args.length == 1 # name.end_with?('=')
|
|
45
|
+
|
|
46
|
+
super unless self.class.method_defined?(name)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Handles Getter method and method with single parameter
|
|
50
|
+
# object.my_name
|
|
51
|
+
# object.my_name('david')
|
|
52
|
+
def add_getter_or_param_method(name)
|
|
53
|
+
# L.progress(1, 'add_getter_or_param_method')
|
|
54
|
+
self.class.class_eval do
|
|
55
|
+
# L.progress(2, 'add_getter_or_param_method')
|
|
56
|
+
name = name.to_s.gsub(/=$/, '')
|
|
57
|
+
# L.progress(3, 'add_getter_or_param_method')
|
|
58
|
+
# L.kv 'name', name
|
|
59
|
+
define_method(name) do |*args|
|
|
60
|
+
# L.progress(4, 'add_getter_or_param_method')
|
|
61
|
+
# L.kv 'add_getter_or_param_method', name
|
|
62
|
+
raise KBuilder::Error, 'Multiple setting values is not supported' if args.length > 1
|
|
63
|
+
|
|
64
|
+
if args.length.zero?
|
|
65
|
+
get_value(name)
|
|
66
|
+
else
|
|
67
|
+
send("#{name}=", args[0])
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Handles Setter method
|
|
74
|
+
# object.my_name = 'david'
|
|
75
|
+
def add_setter_method(name)
|
|
76
|
+
# L.progress(1, 'add_setter_method')
|
|
77
|
+
self.class.class_eval do
|
|
78
|
+
# L.progress(2, 'add_setter_method')
|
|
79
|
+
name = name.to_s.gsub(/=$/, '')
|
|
80
|
+
# L.progress(3, 'add_setter_method')
|
|
81
|
+
# L.kv 'add_setter_method', name
|
|
82
|
+
define_method("#{name}=") do |value|
|
|
83
|
+
# L.progress(4, 'add_setter_method')
|
|
84
|
+
# L.kv 'name', name
|
|
85
|
+
# L.kv 'value', value
|
|
86
|
+
instance_variable_set("@#{name}", value)
|
|
87
|
+
# my_data[name.to_s] = value
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def get_value(name)
|
|
93
|
+
instance_variable_get("@#{name}")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# class L
|
|
98
|
+
# def self.progress(index, label)
|
|
99
|
+
# puts "#{index} - #{label}"
|
|
100
|
+
# end
|
|
101
|
+
|
|
102
|
+
# def self.kv(name, value)
|
|
103
|
+
# puts "#{name.rjust(30)} : #{value}"
|
|
104
|
+
# end
|
|
105
|
+
# end
|
|
106
|
+
end
|
|
@@ -0,0 +1,258 @@
|
|
|
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
|
+
# Refactor: Make Private
|
|
109
|
+
def template_folder=(value)
|
|
110
|
+
hash['template_folder'] = File.expand_path(value)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Getter for template folder
|
|
114
|
+
# Refactor: generate
|
|
115
|
+
def template_folder
|
|
116
|
+
hash['template_folder']
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Global Target folder
|
|
120
|
+
# ----------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
# Fluent setter for global template folder
|
|
123
|
+
def set_global_template_folder(value)
|
|
124
|
+
self.global_template_folder = value
|
|
125
|
+
|
|
126
|
+
self
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Setter for global template folder
|
|
130
|
+
# Refactor: Make Private
|
|
131
|
+
def global_template_folder=(value)
|
|
132
|
+
hash['global_template_folder'] = File.expand_path(value)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Setter for global template folder
|
|
136
|
+
# Refactor: generate
|
|
137
|
+
def global_template_folder
|
|
138
|
+
hash['global_template_folder']
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Internal Actions are considered helpers for the builder, they do
|
|
142
|
+
# something useful, but they do not tend to implement fluent interfaces.
|
|
143
|
+
#
|
|
144
|
+
# They some times do actions, they sometimes return information.
|
|
145
|
+
#
|
|
146
|
+
# NOTE: [SRP] - These methods should probably be converted into objects
|
|
147
|
+
# ----------------------------------------------------------------------
|
|
148
|
+
|
|
149
|
+
# Gets a target_file relative to target folder
|
|
150
|
+
def target_file(file)
|
|
151
|
+
File.join(target_folder, file)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Gets a template_file relative to the template folder
|
|
155
|
+
def template_file(file)
|
|
156
|
+
File.join(template_folder, file)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Gets a global_template_file relative to the global template folder
|
|
160
|
+
def global_template_file(file)
|
|
161
|
+
File.join(global_template_folder, file)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Gets a template_file relative to the template folder, looks first in
|
|
165
|
+
# local template folder and if not found, looks in global template folder
|
|
166
|
+
def find_template_file(file)
|
|
167
|
+
full_file = template_file(file)
|
|
168
|
+
return full_file if File.exist?(full_file)
|
|
169
|
+
|
|
170
|
+
full_file = global_template_file(file)
|
|
171
|
+
return full_file if File.exist?(full_file)
|
|
172
|
+
|
|
173
|
+
# File not found
|
|
174
|
+
nil
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Use content from a a selection of content sources
|
|
178
|
+
#
|
|
179
|
+
# @option opts [String] :content Just pass through the :content as is.
|
|
180
|
+
# @option opts [String] :content_file Read content from the :content_file
|
|
181
|
+
#
|
|
182
|
+
# Future options
|
|
183
|
+
# @option opts [String] :content_loren [TODO]Create Loren Ipsum text as a :content_loren count of words
|
|
184
|
+
# @option opts [String] :content_url Read content from the :content_url
|
|
185
|
+
#
|
|
186
|
+
# @return Returns some content
|
|
187
|
+
def use_content(**opts)
|
|
188
|
+
return opts[:content] unless opts[:content].nil?
|
|
189
|
+
|
|
190
|
+
return unless opts[:content_file]
|
|
191
|
+
|
|
192
|
+
cf = opts[:content_file]
|
|
193
|
+
|
|
194
|
+
return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf)
|
|
195
|
+
|
|
196
|
+
File.read(cf)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Use template from a a selection of template sources
|
|
200
|
+
#
|
|
201
|
+
# @option opts [String] :template Just pass through the :template as is.
|
|
202
|
+
# @option opts [String] :template_file Read template from the :template_file
|
|
203
|
+
#
|
|
204
|
+
# @return Returns some template
|
|
205
|
+
def use_template(**opts)
|
|
206
|
+
return opts[:template] unless opts[:template].nil?
|
|
207
|
+
|
|
208
|
+
return unless opts[:template_file]
|
|
209
|
+
|
|
210
|
+
tf = find_template_file(opts[:template_file])
|
|
211
|
+
|
|
212
|
+
return "template not found: #{opts[:template_file]}" if tf.nil?
|
|
213
|
+
|
|
214
|
+
File.read(tf)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Process content will take any one of the following
|
|
218
|
+
# - Raw content
|
|
219
|
+
# - File based content
|
|
220
|
+
# - Raw template (translated via handlebars)
|
|
221
|
+
# - File base template (translated via handlebars)
|
|
222
|
+
#
|
|
223
|
+
# Process any of the above inputs to create final content output
|
|
224
|
+
#
|
|
225
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
|
226
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be transformed using handlebars
|
|
227
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
|
228
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
|
229
|
+
def process_any_content(**opts)
|
|
230
|
+
raw_content = use_content(**opts)
|
|
231
|
+
|
|
232
|
+
return raw_content if raw_content
|
|
233
|
+
|
|
234
|
+
template_content = use_template(**opts)
|
|
235
|
+
|
|
236
|
+
Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def run_prettier(file, log_level: :log)
|
|
240
|
+
# command = "prettier --check #{file} --write #{file}"
|
|
241
|
+
command = "npx prettier --loglevel #{log_level} --write #{file}"
|
|
242
|
+
|
|
243
|
+
run_command command
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def run_command(command)
|
|
247
|
+
# Deep path create if needed
|
|
248
|
+
FileUtils.mkdir_p(target_folder)
|
|
249
|
+
|
|
250
|
+
build_command = "cd #{target_folder} && #{command}"
|
|
251
|
+
|
|
252
|
+
puts build_command
|
|
253
|
+
|
|
254
|
+
system(build_command)
|
|
255
|
+
end
|
|
256
|
+
alias rc run_command
|
|
257
|
+
end
|
|
258
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
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 < BaseConfiguration
|
|
24
|
+
attr_accessor :target_folder
|
|
25
|
+
attr_accessor :template_folder
|
|
26
|
+
attr_accessor :global_template_folder
|
|
27
|
+
|
|
28
|
+
def initialize
|
|
29
|
+
super
|
|
30
|
+
@target_folder = Dir.getwd
|
|
31
|
+
@template_folder = File.join(Dir.getwd, '.templates')
|
|
32
|
+
@global_template_folder = nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def debug
|
|
36
|
+
puts '-' * 120
|
|
37
|
+
puts 'kbuilder base configuration'
|
|
38
|
+
kv 'target_folder' , target_folder
|
|
39
|
+
kv 'template_folder' , template_folder
|
|
40
|
+
kv 'global_template_folder', global_template_folder
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/k_builder/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.0.23
|
|
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-
|
|
12
|
-
dependencies:
|
|
11
|
+
date: 2021-03-14 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,11 +38,19 @@ 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
|
|
30
45
|
- STORIES.md
|
|
31
46
|
- USAGE.md
|
|
47
|
+
- _out1.png
|
|
48
|
+
- _out2.png
|
|
49
|
+
- _out3.png
|
|
50
|
+
- _out4.png
|
|
51
|
+
- _out5.png
|
|
52
|
+
- _usage_folder_after.png
|
|
53
|
+
- _usage_folder_before.png
|
|
32
54
|
- bin/console
|
|
33
55
|
- bin/k
|
|
34
56
|
- bin/kgitsync
|
|
@@ -38,12 +60,16 @@ files:
|
|
|
38
60
|
- hooks/update-version
|
|
39
61
|
- k_builder.gemspec
|
|
40
62
|
- lib/k_builder.rb
|
|
63
|
+
- lib/k_builder/base_builder.rb
|
|
64
|
+
- lib/k_builder/base_configuration.rb
|
|
65
|
+
- lib/k_builder/builder.rb
|
|
66
|
+
- lib/k_builder/configuration.rb
|
|
41
67
|
- lib/k_builder/version.rb
|
|
42
|
-
homepage: http://appydave.com
|
|
68
|
+
homepage: http://appydave.com
|
|
43
69
|
licenses:
|
|
44
70
|
- MIT
|
|
45
71
|
metadata:
|
|
46
|
-
homepage_uri: http://appydave.com
|
|
72
|
+
homepage_uri: http://appydave.com
|
|
47
73
|
source_code_uri: https://github.com/klueless-io/k_builder
|
|
48
74
|
changelog_uri: https://github.com/klueless-io/k_builder/commits/master
|
|
49
75
|
post_install_message:
|