k_starter 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/generators/01-bootstrap.rb +16 -16
  3. data/.rubocop.yml +14 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +22 -0
  6. data/README.md +1 -1
  7. data/exe/k_starter +15 -0
  8. data/ext/k_starter/extconf.rb +5 -0
  9. data/ext/k_starter/k_starter.c +9 -0
  10. data/ext/k_starter/k_starter.h +6 -0
  11. data/lib/k_starter/app.rb +16 -0
  12. data/lib/k_starter/app_generator.rb +198 -0
  13. data/lib/k_starter/cli.rb +63 -0
  14. data/lib/k_starter/commands/.keep +1 -0
  15. data/lib/k_starter/commands/command.rb +54 -0
  16. data/lib/k_starter/commands/configuration/configuration_menu.rb +46 -0
  17. data/lib/k_starter/commands/project/bootstrap_project.rb +28 -0
  18. data/lib/k_starter/commands/project/edit_project.rb +34 -0
  19. data/lib/k_starter/commands/project/new_project.rb +28 -0
  20. data/lib/k_starter/commands/project/project_menu.rb +51 -0
  21. data/lib/k_starter/commands/project/select_new_project_type.rb +44 -0
  22. data/lib/k_starter/database/base_model.rb +21 -0
  23. data/lib/k_starter/database/config_model.rb +99 -0
  24. data/lib/k_starter/database/project_model.rb +94 -0
  25. data/lib/k_starter/map.rb +46 -0
  26. data/lib/k_starter/questions/ask_questions.rb +20 -0
  27. data/lib/k_starter/questions/base_question.rb +208 -0
  28. data/lib/k_starter/questions/gem.rb +132 -0
  29. data/lib/k_starter/questions/rails.rb +162 -0
  30. data/lib/k_starter/questions/svelte.rb +52 -0
  31. data/lib/k_starter/r7_hotwire.rb +98 -0
  32. data/lib/k_starter/schema.rb +89 -0
  33. data/lib/k_starter/starters/base.rb +80 -0
  34. data/lib/k_starter/starters/gem.rb +71 -0
  35. data/lib/k_starter/starters/nuxt.rb +29 -0
  36. data/lib/k_starter/starters/rails.rb +29 -0
  37. data/lib/k_starter/starters/svelte.rb +45 -0
  38. data/lib/k_starter/tty_helpers.rb +118 -0
  39. data/lib/k_starter/version.rb +1 -1
  40. data/lib/k_starter.rb +44 -1
  41. data/package-lock.json +2 -2
  42. data/package.json +1 -1
  43. metadata +172 -1
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KStarter
4
+ module Questions
5
+ # Ask code generations for a new GEM.
6
+ class BaseGem < BaseQuestion
7
+ attr_reader :exe # has executable folder
8
+ attr_reader :coc # has code of conduct
9
+ attr_reader :mit # has MIT license
10
+ attr_reader :rspec # has rspec tests
11
+
12
+ def initialize(**args)
13
+ args = { type: :gem }.merge(args)
14
+ super(**args)
15
+ end
16
+
17
+ def ask_questions
18
+ ask_name
19
+ ask_root_path
20
+ ask_github_key
21
+ ask_description
22
+ story_questions
23
+ klue_template_questions
24
+
25
+ ask_exe
26
+ ask_coc
27
+ ask_mit
28
+ ask_rspec
29
+ end
30
+
31
+ def to_h
32
+ super.merge(
33
+ {
34
+ exe: exe,
35
+ coc: coc,
36
+ mit: mit,
37
+ rspec: rspec
38
+ }
39
+ )
40
+ end
41
+
42
+ def to_dom
43
+ KStarter::Schema::GemProject.new(to_h)
44
+ end
45
+
46
+ private
47
+
48
+ def initialize_attributes(**args)
49
+ super(**args)
50
+
51
+ @exe = args[:exe]
52
+ @coc = args[:coc]
53
+ @mit = args[:mit]
54
+ @rspec = args[:rspec]
55
+ end
56
+
57
+ def apply_attribute_defaults
58
+ default_story_active
59
+ default_klue_template_active
60
+
61
+ default_exe
62
+ default_coc
63
+ default_mit
64
+ default_rspec
65
+ end
66
+
67
+ def question
68
+ @question ||= prompt
69
+ end
70
+
71
+ def ask_name
72
+ @name = question.ask('Name (ruby GEM)') do |q|
73
+ q.default(name) unless name.nil?
74
+ q.required(true, 'GEM name is required, and can only contain letters, numbers, and underscores.')
75
+ q.validate(/\A\w+\Z/)
76
+ end
77
+ end
78
+
79
+ def ask_exe
80
+ @exe = question.yes?('Has executable folder?', default: exe)
81
+ end
82
+
83
+ def default_exe
84
+ @exe = false if @exe.nil?
85
+ end
86
+
87
+ def ask_coc
88
+ @coc = question.yes?('Has code of conduct?', default: coc)
89
+ end
90
+
91
+ def default_coc
92
+ @coc = true if @coc.nil?
93
+ end
94
+
95
+ def ask_mit
96
+ @mit = question.yes?('Has MIT license?', default: mit)
97
+ end
98
+
99
+ def default_mit
100
+ @mit = true if @mit.nil?
101
+ end
102
+
103
+ def ask_rspec
104
+ @rspec = question.yes?('Has rspec tests?', default: rspec)
105
+ end
106
+
107
+ def default_rspec
108
+ @rspec = true if @rspec.nil?
109
+ end
110
+ end
111
+
112
+ # Ask code generations for a new Ruby GEM project.
113
+ class LibraryGem < KStarter::Questions::BaseGem
114
+ def initialize(**args)
115
+ args = { variant: :library }.merge(args)
116
+ super(**args)
117
+ end
118
+ end
119
+
120
+ # Ask code generations for a new Ruby command line GEM project.
121
+ class CliGem < KStarter::Questions::BaseGem
122
+ def initialize(**args)
123
+ args = { variant: :cli }.merge(args)
124
+ super(**args)
125
+ end
126
+
127
+ def default_exe
128
+ @exe = true if @exe.nil?
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KStarter
4
+ module Questions
5
+ # Ask code generations for a new GEM.
6
+ class Rails < BaseQuestion
7
+ attr_reader :include_action_text
8
+ attr_reader :include_active_storage
9
+ attr_reader :include_sample_models
10
+ attr_reader :include_javascript_libraries
11
+ attr_reader :include_devise
12
+ attr_reader :include_rspec
13
+ attr_reader :include_common_pages
14
+ attr_reader :run_db_migrate
15
+
16
+ def initialize(**args)
17
+ args = { type: 'rails' }.merge(args)
18
+ super(**args)
19
+ end
20
+
21
+ def ask_questions
22
+ ask_name
23
+ ask_root_path
24
+ ask_github_key
25
+ ask_description
26
+ story_questions
27
+ klue_template_questions
28
+
29
+ ask_include_action_text
30
+ ask_include_active_storage
31
+ ask_include_sample_models
32
+ ask_include_javascript_libraries
33
+ ask_include_devise
34
+ ask_include_rspec
35
+ ask_include_common_pages
36
+ ask_run_db_migrate
37
+ end
38
+
39
+ def to_h
40
+ super.merge(
41
+ {
42
+ include_action_text: include_action_text,
43
+ include_active_storage: include_active_storage,
44
+ include_sample_models: include_sample_models,
45
+ include_javascript_libraries: include_javascript_libraries,
46
+ include_devise: include_devise,
47
+ include_rspec: include_rspec,
48
+ include_common_pages: include_common_pages,
49
+ run_db_migrate: run_db_migrate
50
+ }
51
+ )
52
+ end
53
+
54
+ def to_dom
55
+ KStarter::Schema::RailsProject.new(to_h)
56
+ end
57
+
58
+ private
59
+
60
+ def initialize_attributes(**args)
61
+ super(**args)
62
+
63
+ @include_action_text = args[:include_action_text]
64
+ @include_active_storage = args[:include_active_storage]
65
+ @include_sample_models = args[:include_sample_models]
66
+ @include_javascript_libraries = args[:include_javascript_libraries]
67
+ @include_devise = args[:include_devise]
68
+ @include_rspec = args[:include_rspec]
69
+ @include_common_pages = args[:include_common_pages]
70
+ @run_db_migrate = args[:run_db_migrate]
71
+ end
72
+
73
+ def apply_attribute_defaults
74
+ default_story_active
75
+ default_klue_template_active
76
+
77
+ default_include_action_text
78
+ default_include_active_storage
79
+ default_include_sample_models
80
+ default_include_javascript_libraries
81
+ default_include_devise
82
+ default_include_rspec
83
+ default_include_common_pages
84
+ default_run_db_migrate
85
+ end
86
+
87
+ def ask_name
88
+ @name = question.ask('Name (rails application)') do |q|
89
+ q.default(name) unless name.nil?
90
+ q.required(true, 'Rails application name is required, and can only contain letters, numbers, and underscores.')
91
+ q.validate(/\A\w+\Z/)
92
+ end
93
+ end
94
+
95
+ def ask_include_action_text
96
+ @include_action_text = question.yes?('Include Action Text', default: include_action_text)
97
+ end
98
+
99
+ def ask_include_active_storage
100
+ @include_active_storage = question.yes?('Include Active Storage', default: include_active_storage)
101
+ end
102
+
103
+ def ask_include_sample_models
104
+ @include_sample_models = question.yes?('Include Sample Models', default: include_sample_models)
105
+ end
106
+
107
+ def ask_include_javascript_libraries
108
+ @include_javascript_libraries = question.yes?('Include Javascript Libraries', default: include_javascript_libraries)
109
+ end
110
+
111
+ def ask_include_devise
112
+ @include_devise = question.yes?('Include Devise', default: include_devise)
113
+ end
114
+
115
+ def ask_include_rspec
116
+ @include_rspec = question.yes?('Include Rspec', default: include_rspec)
117
+ end
118
+
119
+ def ask_include_common_pages
120
+ @include_common_pages = question.yes?('Include Common Pages', default: include_common_pages)
121
+ end
122
+
123
+ def ask_run_db_migrate
124
+ @run_db_migrate = question.yes?('DB Migrate', default: run_db_migrate)
125
+ end
126
+
127
+ # defaults
128
+
129
+ def default_include_action_text
130
+ @include_action_text = true if @include_action_text.nil?
131
+ end
132
+
133
+ def default_include_active_storage
134
+ @include_active_storage = true if @include_active_storage.nil?
135
+ end
136
+
137
+ def default_include_sample_models
138
+ @include_sample_models = true if @include_sample_models.nil?
139
+ end
140
+
141
+ def default_include_javascript_libraries
142
+ @include_javascript_libraries = true if @include_javascript_libraries.nil?
143
+ end
144
+
145
+ def default_include_devise
146
+ @include_devise = true if @include_devise.nil?
147
+ end
148
+
149
+ def default_include_rspec
150
+ @include_rspec = true if @include_rspec.nil?
151
+ end
152
+
153
+ def default_include_common_pages
154
+ @include_common_pages = true if @include_common_pages.nil?
155
+ end
156
+
157
+ def default_run_db_migrate
158
+ @run_db_migrate = true if @run_db_migrate.nil?
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KStarter
4
+ module Questions
5
+ # Ask code generations for a new GEM.
6
+ class Svelte < BaseQuestion
7
+ def initialize(**args)
8
+ args = { type: :svelte }.merge(args)
9
+ super(**args)
10
+ end
11
+
12
+ def ask_questions
13
+ ask_name
14
+ ask_root_path
15
+ ask_github_key
16
+ ask_description
17
+ story_questions
18
+ klue_template_questions
19
+ end
20
+
21
+ def to_h
22
+ super.merge(
23
+ {
24
+ }
25
+ )
26
+ end
27
+
28
+ def to_dom
29
+ KStarter::Schema::SvelteProject.new(to_h)
30
+ end
31
+
32
+ private
33
+
34
+ def apply_attribute_defaults
35
+ default_story_active
36
+ default_klue_template_active
37
+ end
38
+
39
+ def question
40
+ @question ||= prompt
41
+ end
42
+
43
+ def ask_name
44
+ @name = question.ask('Name (Svelte Application)') do |q|
45
+ q.default(name) unless name.nil?
46
+ q.required(true, 'Svelte application name is required, and can only contain letters, numbers, and underscores.')
47
+ q.validate(/\A\w+\Z/)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require 'uri'
4
+ # require 'net/http'
5
+ require 'active_model'
6
+ require 'pry'
7
+ require_relative 'base_template'
8
+
9
+ # R7HotwireTemplate
10
+ class R7HotwireTemplate < BaseTemplate
11
+ attr_reader :host
12
+
13
+ def customize_template
14
+ gac('Base Rails 7 image created')
15
+
16
+ settings_for_asset_management
17
+
18
+ ask_questions
19
+ add_gems
20
+ add_gem_groups
21
+ end
22
+
23
+ # ./bin/rails javascript:install:esbuild
24
+ def after_bundle
25
+ add_action_text if action_text?
26
+ add_active_storage if active_storage?
27
+ add_devise if devise?
28
+ add_rspec if rspec?
29
+ add_javascript_libraries if javascript_libraries?
30
+
31
+ gac('Base Rails 7 default structure created')
32
+
33
+ setup_models if sample_models?
34
+ setup_common_pages if common_pages?
35
+
36
+ rails_command('db:migrate') if db_migrate?
37
+ end
38
+
39
+ private
40
+
41
+ def add_devise
42
+ run 'bundle add devise'
43
+
44
+ Bundler.with_unbundled_env { run 'bundle install' }
45
+
46
+ rails_command 'generate devise:install'
47
+
48
+ run 'rails generate devise User role:integer'
49
+
50
+ alter_first_file('db/migrate/*_create_users.rb') do |file|
51
+ host.in_root do
52
+ host.gsub_file(file,
53
+ 't.integer :role',
54
+ 't.integer :role, default: 0')
55
+ end
56
+ end
57
+
58
+ rails_command 'generate devise:views'
59
+ end
60
+
61
+ def ask_questions
62
+ self.include_action_text = no?("Add action text 'Rails'?")
63
+ self.include_active_storage = no?("Add active storage 'Rails'?")
64
+ self.include_javascript_libraries = no?("Add javascript libraries 'Pinned'?") # this is if using importmap
65
+ self.include_sample_models = no?('Add sample models?')
66
+ self.include_common_pages = yes?('Add common pages?')
67
+ self.include_devise = no?('Add devise?') # Alter t.integer :role, default: 0
68
+ self.include_rspec = no?('Add rspec?')
69
+ self.run_db_migrate = yes?('Run db:migrate?')
70
+ end
71
+
72
+ def setup_models
73
+ g_scaffold('post', 'title', 'content:text')
74
+ g_scaffold('book', 'title', 'content:text')
75
+ g_resource('comment', 'post:references', 'content:text')
76
+ g_mailer('posts', 'submitted', 'broken')
77
+ end
78
+
79
+ def setup_common_pages
80
+ g_controller('home', 'index')
81
+ host.route("root to: 'home#index'")
82
+ # g_controller("pages", "home", "about")
83
+ # host.route("root to: 'pages#home'")
84
+ end
85
+
86
+ def add_javascript_libraries
87
+ # see: https://youtube.com/clip/Ugkx_tDcsUclZ-GR1Ck6liDKrlvmf38r92mw
88
+ # host.run("bin/importmap pin local-time")
89
+ host.run('bin/importmap pin local-time --download')
90
+ end
91
+ end
92
+
93
+ setup_rails = R7HotwireTemplate.new(self)
94
+ setup_rails.customize_template
95
+
96
+ after_bundle do
97
+ setup_rails.after_bundle
98
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ include Dry.Types()
5
+ end
6
+
7
+ module KStarter
8
+ # Schema for storing model data for projects and other configuration data
9
+ module Schema
10
+ # Configuration class for the project types
11
+ class ProjectType < Dry::Struct
12
+ attribute :type , Types::Coercible::Symbol
13
+ attribute :variant , Types::Coercible::Symbol.optional.default(nil)
14
+ attribute :path , Types::Strict::String
15
+ end
16
+
17
+ class Github < Dry::Struct
18
+ attribute :user , Types::Strict::String
19
+ attribute :organizations , Types::Array.of(Types::Coercible::String)
20
+ end
21
+
22
+ # User story node
23
+ class Story < Dry::Struct
24
+ attribute :active , Types::Strict::Bool
25
+ attribute :actor , Types::Strict::String.optional.default(nil)
26
+ attribute :problem , Types::Strict::String.optional.default(nil)
27
+ attribute :solution , Types::Strict::String.optional.default(nil)
28
+ attribute :user_story , Types::Strict::String.optional.default(nil)
29
+ end
30
+
31
+ # Klue template node
32
+ class KlueTemplate < Dry::Struct
33
+ attribute :active , Types::Strict::Bool
34
+ attribute :name , Types::Strict::String.optional.default(nil)
35
+ end
36
+
37
+ # Base class for project data
38
+ class BaseProject < Dry::Struct
39
+ attribute :name , Types::Strict::String
40
+ attribute :type , Types::Coercible::Symbol
41
+ attribute :variant , Types::Coercible::Symbol.optional.default(nil)
42
+ attribute :root_path , Types::Strict::String # .constructor { |path| File.expand_path(path) }
43
+ attribute :description , Types::Strict::String.optional.default(nil)
44
+ attribute :story , KStarter::Schema::Story
45
+ attribute :klue_template , KStarter::Schema::KlueTemplate
46
+ attribute :github_key , Types::Strict::String
47
+
48
+ def expanded_project_path
49
+ File.join(expanded_root_path, name)
50
+ end
51
+
52
+ def expanded_root_path
53
+ File.expand_path(root_path)
54
+ end
55
+
56
+ def github_account_type
57
+ github_key == App.config.github_user ? :user : :organization
58
+ end
59
+
60
+ def github_organization
61
+ github_account_type == :organization ? github_key : nil
62
+ end
63
+ end
64
+
65
+ class RailsProject < BaseProject
66
+ attribute :include_action_text , Types::Strict::Bool
67
+ attribute :include_active_storage , Types::Strict::Bool
68
+ attribute :include_sample_models , Types::Strict::Bool
69
+ attribute :include_javascript_libraries , Types::Strict::Bool
70
+ attribute :include_devise , Types::Strict::Bool
71
+ attribute :include_rspec , Types::Strict::Bool
72
+ attribute :include_common_pages , Types::Strict::Bool
73
+ attribute :run_db_migrate , Types::Strict::Bool
74
+ end
75
+
76
+ class GemProject < BaseProject
77
+ attribute :exe , Types::Strict::Bool
78
+ attribute :coc , Types::Strict::Bool
79
+ attribute :mit , Types::Strict::Bool
80
+ attribute :rspec , Types::Strict::Bool
81
+ end
82
+
83
+ class SvelteProject < BaseProject
84
+ end
85
+
86
+ class NuxtProject < BaseProject
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KStarter
4
+ module Starters
5
+ # Generate command line for a new ruby gem project.
6
+ class Base
7
+ include TtyHelpers
8
+
9
+ attr_reader :project
10
+ attr_reader :code_open_delay
11
+
12
+ def initialize(project, **args)
13
+ @project = project
14
+ @code_open_delay = args[:code_open_delay] || 0
15
+ end
16
+
17
+ def system_in_root(script)
18
+ Dir.chdir(project.expanded_root_path) do
19
+ system script
20
+ end
21
+ end
22
+
23
+ def system_in_project(script)
24
+ Dir.chdir(project.expanded_project_path) do
25
+ system script
26
+ end
27
+ end
28
+
29
+ def project_path_exist?
30
+ File.exist?(project.expanded_project_path)
31
+ end
32
+
33
+ def project_path_delete
34
+ return unless project_path_exist?
35
+
36
+ FileUtils.rm_rf(project.expanded_project_path)
37
+ end
38
+
39
+ def project_open_in_vscode
40
+ sleep code_open_delay if code_open_delay.positive?
41
+
42
+ Dir.chdir(project.expanded_project_path) do
43
+ system('code .')
44
+ end
45
+ end
46
+
47
+ def ask_destroy_existing_project
48
+ question.yes?('Do you want to destroy the existing project folder')
49
+ end
50
+
51
+ def ask_exit_if_project_exists
52
+ question.yes?('This project exists. Do you want to cancel new project creation?')
53
+ end
54
+
55
+ def exiting(message = 'Exiting')
56
+ question.warn(message)
57
+ nil
58
+ end
59
+
60
+ def create_kbuilder
61
+ KManager::Cli::Commands::New.new.call(
62
+ project_folder: project.expanded_project_path,
63
+ builder_folder: File.join(project.expanded_project_path, '.builders'),
64
+ description: project.description,
65
+ user_story: project.story.user_story,
66
+ repo_organization: project.github_organization,
67
+ template: project.klue_template.name,
68
+ log_level: nil,
69
+ force: true
70
+ )
71
+ end
72
+
73
+ private
74
+
75
+ def question
76
+ @question ||= prompt
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Examples
4
+ # bundle gem --coc --ci=github --exe --linter=rubocop --test=rspec --mit k_genesis
5
+ # bundle gem --coc --test=rspec --mit k_genesis
6
+ # bundle gem --coc --test=rspec --mit conventional_gitflow
7
+ # bundle gem --coc --test=rspec --mit k_director
8
+ # bundle gem --coc --test=rspec --mit k_config
9
+ # bundle gem --coc --test=rspec --mit funky
10
+ # bundle gem --coc --test=rspec --mit --linter=rubocop --ci-github cmdlet
11
+ # bundle gem --coc --test=rspec --mit cmdlet
12
+ # bundle gem --coc --test=rspec --mit drawio_dsl
13
+ # bundle gem --coc --test=rspec --mit tailwind_dsl
14
+ # bundle gem --coc --test=rspec --mit test-google-cloud-functions
15
+ # bundle gem --coc --test=rspec --mit handlebarsjs
16
+ # bundle gem --coc --test=rspec --mit k_starter
17
+
18
+ module KStarter
19
+ module Starters
20
+ # Generate command line for a new ruby gem project.
21
+ class Gem < KStarter::Starters::Base
22
+ def execute
23
+ create_gem
24
+ create_kbuilder
25
+
26
+ project_open_in_vscode
27
+ end
28
+
29
+ private
30
+
31
+ def create_gem
32
+ if project_path_exist?
33
+ return exiting if ask_exit_if_project_exists
34
+
35
+ project_path_delete if ask_destroy_existing_project
36
+ end
37
+
38
+ system_in_root(build_create_gem_bash)
39
+ end
40
+
41
+ def build_create_gem_bash
42
+ <<-BASH
43
+
44
+ echo "Generating gem project #{project.name}..."
45
+ echo "Ruby version:"
46
+ ruby -v
47
+ echo "Current folder: "
48
+ pwd
49
+ # create the gem
50
+ #{build_bundle_gem}
51
+
52
+ BASH
53
+ end
54
+
55
+ # rubocop:disable Metrics/AbcSize
56
+ def build_bundle_gem
57
+ # bundle gem --coc --exe --test=rspec --mit k_genesis
58
+
59
+ bundle_gem = []
60
+ bundle_gem << 'bundle gem'
61
+ bundle_gem << '--coc' if project.coc
62
+ bundle_gem << '--exe' if project.exe
63
+ bundle_gem << '--mit' if project.mit
64
+ bundle_gem << '--test=rspec' if project.rspec
65
+ bundle_gem << project.name.to_s
66
+ bundle_gem.join(' ')
67
+ end
68
+ # rubocop:enable Metrics/AbcSize
69
+ end
70
+ end
71
+ end