app_archetype 1.2.8 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +36 -9
  3. data/README.md +150 -28
  4. data/app_archetype.gemspec +3 -0
  5. data/bin/app_archetype +20 -0
  6. data/bin/archetype +1 -1
  7. data/lib/app_archetype/cli.rb +171 -139
  8. data/lib/app_archetype/commands/delete_template.rb +58 -0
  9. data/lib/app_archetype/commands/find_templates.rb +66 -0
  10. data/lib/app_archetype/commands/list_templates.rb +49 -0
  11. data/lib/app_archetype/commands/new_template.rb +42 -0
  12. data/lib/app_archetype/commands/open_manifest.rb +48 -0
  13. data/lib/app_archetype/commands/print_path.rb +20 -0
  14. data/lib/app_archetype/commands/print_template_variables.rb +67 -0
  15. data/lib/app_archetype/commands/print_version.rb +19 -0
  16. data/lib/app_archetype/commands/render_template.rb +178 -0
  17. data/lib/app_archetype/commands.rb +13 -0
  18. data/lib/app_archetype/generators.rb +1 -1
  19. data/lib/app_archetype/template_manager.rb +9 -0
  20. data/lib/app_archetype/version.rb +1 -1
  21. data/lib/app_archetype.rb +40 -23
  22. data/scripts/create_new_command +32 -0
  23. data/scripts/generators/command/manifest.json +15 -0
  24. data/scripts/generators/command/template/lib/app_archetype/commands/{{command_name.snake_case}}.rb.hbs +17 -0
  25. data/spec/app_archetype/cli/presenters_spec.rb +99 -99
  26. data/spec/app_archetype/cli/prompts_spec.rb +291 -291
  27. data/spec/app_archetype/cli_spec.rb +427 -65
  28. data/spec/app_archetype/commands/delete_template_spec.rb +132 -0
  29. data/spec/app_archetype/commands/find_templates_spec.rb +130 -0
  30. data/spec/app_archetype/commands/list_templates_spec.rb +55 -0
  31. data/spec/app_archetype/commands/new_template_spec.rb +84 -0
  32. data/spec/app_archetype/commands/open_manifest_spec.rb +113 -0
  33. data/spec/app_archetype/commands/print_path_spec.rb +22 -0
  34. data/spec/app_archetype/commands/print_template_variables_spec.rb +158 -0
  35. data/spec/app_archetype/commands/print_version_spec.rb +21 -0
  36. data/spec/app_archetype/commands/render_template_spec.rb +479 -0
  37. data/spec/app_archetype/generators_spec.rb +1 -1
  38. data/spec/app_archetype/template_manager_spec.rb +32 -0
  39. data/spec/app_archetype_spec.rb +65 -0
  40. metadata +79 -4
  41. data/lib/app_archetype/cli/presenters.rb +0 -106
  42. data/lib/app_archetype/cli/prompts.rb +0 -152
@@ -0,0 +1,178 @@
1
+ require 'tty-prompt'
2
+
3
+ module AppArchetype
4
+ module Commands
5
+ # Prompts user for variable values and renders template to disk
6
+ class RenderTemplate
7
+ def initialize(manager, destination_path, options = Hashie::Mash.new)
8
+ @manager = manager
9
+ @destination_path = destination_path
10
+ @options = options
11
+ @prompt = TTY::Prompt.new
12
+ end
13
+
14
+ ##
15
+ # Renders a template with instructions described
16
+ # in the manifest.
17
+ #
18
+ # First it looks to the options to determine the
19
+ # name of the manifest. If one is not provided
20
+ # then the user will be prompted to choose a manifest
21
+ # from the list.
22
+ #
23
+ # The manager will then attempt to find the manifest.
24
+ # if one is not found then a RuntimeError will be raised.
25
+ #
26
+ # Once the manifest is loaded the template will be loaded
27
+ # into memory.
28
+ #
29
+ # Then the variables specified in the manifest are
30
+ # resolved. This involves the command prompting
31
+ # for values.
32
+ #
33
+ # A plan can then be constructed with the template and
34
+ # variables, this plan is then devised and executed.
35
+ #
36
+ # When the render is successful a success message
37
+ # is sent to STDOUT to confirm the operation was
38
+ # successful.
39
+ #
40
+ def run
41
+ name = @options.name
42
+ name ||= @prompt.select('Please choose manifest', @manager.manifest_names)
43
+
44
+ manifest = @manager.find_by_name(name)
45
+
46
+ unless manifest
47
+ puts "✖ No template with name `#{name}` found."
48
+ return
49
+ end
50
+
51
+ template = manifest.template
52
+ template.load
53
+
54
+ resolve_variables(manifest)
55
+ render_template(
56
+ manifest,
57
+ template,
58
+ overwrite: @options.overwrite
59
+ )
60
+
61
+ puts("✔ Rendered #{name} to #{@destination_path}")
62
+ end
63
+
64
+ ##
65
+ # Prompts user for values for each variable
66
+ # specified in the given manifest. And then
67
+ # sets the value of those variables to the
68
+ # answers to the prompts.
69
+ #
70
+ # @param[AppArchetype::Template::Manifest] manifest
71
+ #
72
+ def resolve_variables(manifest)
73
+ manifest.variables.all.each do |var|
74
+ value = variable_prompt_for(var)
75
+ var.set!(value)
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Builds plan to render template and executes
81
+ # it - essentially rendering the template to
82
+ # the output location
83
+ #
84
+ # @param [AppArchetype::Template::Manifest] manifest
85
+ # @param [AppArchetype::Template] template
86
+ # @param [Boolean] overwrite
87
+ #
88
+ def render_template(
89
+ manifest,
90
+ template,
91
+ overwrite: false
92
+ )
93
+ plan = AppArchetype::Template::Plan.new(
94
+ template,
95
+ manifest.variables,
96
+ destination_path: @destination_path,
97
+ overwrite: overwrite
98
+ )
99
+
100
+ plan.devise
101
+ plan.execute
102
+ end
103
+
104
+ ##
105
+ # Resolver for a given variable
106
+ #
107
+ # First, it will set the value if the value is set in
108
+ # the manifest.
109
+ #
110
+ # Otherwise it will call a function that prompts
111
+ # a user for input depending on type.
112
+ #
113
+ # By default it will call the string variable prompt
114
+ #
115
+ # @param [AppArchetype::Template::Variable] var
116
+ #
117
+ # @return [Object]
118
+ #
119
+ def variable_prompt_for(var)
120
+ return var.value if var.value?
121
+ return boolean_variable_prompt_for(var) if var.type == 'boolean'
122
+ return integer_variable_prompt_for(var) if var.type == 'integer'
123
+
124
+ string_variable_prompt_for(var)
125
+ end
126
+
127
+ ##
128
+ # Prompts and then asks for boolean input for
129
+ # a boolean variable
130
+ #
131
+ # @param [AppArchetype::Template::Variable] var
132
+ #
133
+ # @return [Boolean]
134
+ #
135
+ def boolean_variable_prompt_for(var)
136
+ puts "• #{var.name} (#{var.description})"
137
+
138
+ @prompt.yes?(
139
+ "Enter value for `#{var.name}` variable:",
140
+ default: var.default
141
+ )
142
+ end
143
+
144
+ ##
145
+ # Prompts and then asks for integer input for
146
+ # a integer variable
147
+ #
148
+ # @param [AppArchetype::Template::Variable] var
149
+ #
150
+ # @return [Integer]
151
+ #
152
+ def integer_variable_prompt_for(var)
153
+ puts "• #{var.name} (#{var.description})"
154
+
155
+ @prompt.ask("Enter value for `#{var.name}` variable:",
156
+ convert: :int,
157
+ default: var.default)
158
+ end
159
+
160
+ ##
161
+ # Prompts and then asks for string input for
162
+ # a string variable
163
+ #
164
+ # @param [AppArchetype::Template::Variable] var
165
+ #
166
+ # @return [String]
167
+ #
168
+ def string_variable_prompt_for(var)
169
+ puts "• #{var.name} (#{var.description})"
170
+
171
+ @prompt.ask(
172
+ "Enter value for `#{var.name}` variable:",
173
+ default: var.default
174
+ )
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,13 @@
1
+ require 'hashie'
2
+
3
+ COMMANDS = File.join(__dir__, 'commands', '*.rb')
4
+
5
+ Dir[COMMANDS].sort.each do |file|
6
+ require file
7
+ end
8
+
9
+ module AppArchetype
10
+ # Module for CLI command classes
11
+ module Commands
12
+ end
13
+ end
@@ -60,7 +60,7 @@ module AppArchetype
60
60
  # @param [String] path
61
61
  #
62
62
  def render_empty_template(name, path)
63
- template_path = File.join(path, name)
63
+ template_path = File.join(path, 'template')
64
64
  manifest_path = File.join(path, 'manifest.json')
65
65
  readme_path = File.join(path, 'README.md')
66
66
 
@@ -109,5 +109,14 @@ module AppArchetype
109
109
 
110
110
  results.first
111
111
  end
112
+
113
+ ##
114
+ # Returns a list of manifest names from loaded templates
115
+ #
116
+ # @return [Array]
117
+ #
118
+ def manifest_names
119
+ @manifests.map(&:name)
120
+ end
112
121
  end
113
122
  end
@@ -2,5 +2,5 @@ module AppArchetype
2
2
  ##
3
3
  # AppArchetype version
4
4
  #
5
- VERSION = '1.2.8'.freeze
5
+ VERSION = '1.3.0'.freeze
6
6
  end
data/lib/app_archetype.rb CHANGED
@@ -7,41 +7,58 @@ require 'app_archetype/template_manager'
7
7
  require 'app_archetype/renderer'
8
8
  require 'app_archetype/generators'
9
9
 
10
- require 'app_archetype/cli/prompts'
11
-
12
10
  require 'app_archetype/version'
11
+ require_relative './app_archetype/commands'
13
12
 
14
13
  # AppArchetype is the namespace for app_archetype
15
14
  module AppArchetype
16
- def self.render(
17
- name,
18
- templates_dir,
19
- destination_path: Dir.pwd,
20
- overwrite: true,
21
- variables: []
15
+ ##
16
+ # Self contained template render method
17
+ #
18
+ # Takes collection directory and template name to
19
+ # load a new manager and find the desired template
20
+ #
21
+ # Then executes a render template command with the
22
+ # found template
23
+ #
24
+ # Returns the manifest rendered. Target can optionally
25
+ # be set to overwrite
26
+ #
27
+ # This method is to be used for self contained rendering#
28
+ # scripts.
29
+ #
30
+ # @param [String] collection_dir
31
+ # @param [String] template_name
32
+ # @param [String] destination_path
33
+ # @param [Boolean] overwrite
34
+ #
35
+ # @return [AppArchetype::Template::Manifest]
36
+ #
37
+ def self.render_template(
38
+ collection_dir: ENV.fetch('ARCHETYPE_TEMPLATE_DIR'),
39
+ template_name: '',
40
+ destination_path: '',
41
+ overwrite: false
22
42
  )
23
- manifest_file = File.join(templates_dir, name, 'manifest.json')
43
+ manager = AppArchetype::TemplateManager.new(collection_dir)
44
+ manager.load
24
45
 
25
- manifest = AppArchetype::Template::Manifest.new_from_file(manifest_file)
46
+ manifest = manager.find_by_name(template_name)
26
47
 
27
48
  template = manifest.template
28
49
  template.load
29
50
 
30
- variables.each { |var| manifest.variables.add(var) }
31
-
32
- manifest.variables.all.each do |var|
33
- value = AppArchetype::CLI::Prompts.variable_prompt_for(var)
34
- var.set!(value)
35
- end
36
-
37
- plan = AppArchetype::Template::Plan.new(
38
- template,
39
- manifest.variables,
40
- destination_path: destination_path,
51
+ options = Hashie::Mash.new(
52
+ name: template_name,
41
53
  overwrite: overwrite
42
54
  )
43
55
 
44
- plan.devise
45
- plan.execute
56
+ command = AppArchetype::Commands::RenderTemplate.new(
57
+ manager, destination_path, options
58
+ )
59
+
60
+ command.run
61
+
62
+ manifest
46
63
  end
47
64
  end
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/app_archetype'
4
+
5
+ puts 'CREATE NEW COMMAND'
6
+
7
+ manifest = AppArchetype.render_template(
8
+ collection_dir: File.join(__dir__, 'generators'),
9
+ template_name: 'command',
10
+ destination_path: File.expand_path(File.join(__dir__, '..'))
11
+ )
12
+
13
+ command_name = manifest.variables.get('command_name').value
14
+
15
+ next_steps = <<~TEXT
16
+ ✔ Command created
17
+
18
+ TODO:
19
+
20
+ Add the following to cli.rb within AppArchetype::CLI:
21
+
22
+ ```
23
+ desc '#{command_name.snake_case}', 'TODO: description'
24
+
25
+ def #{command_name.snake_case}
26
+ cmd = AppArchetype::Commands::#{command_name.camel_case}.new(options)
27
+ cmd.run
28
+ end
29
+ ```
30
+ TEXT
31
+
32
+ puts next_steps
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "command",
3
+ "version": "1.0.0",
4
+ "metadata": {
5
+ "app_archetype": {
6
+ "version": "1.2.7"
7
+ }
8
+ },
9
+ "variables": {
10
+ "command_name": {
11
+ "type": "string",
12
+ "description": "Name of command (i.e. create_new_thing)"
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,17 @@
1
+ require 'tty-prompt'
2
+
3
+ module AppArchetype
4
+ module Commands
5
+ class {{command_name.camel_case}}
6
+ def initialize(manager, options)
7
+ @manager = manager
8
+ @options = options
9
+ @prompt = TTY::Prompt.new
10
+ end
11
+
12
+ def run
13
+ puts('✔ {{command_name.snake_case}} complete')
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,99 +1,99 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe AppArchetype::CLI::Presenters do
4
- describe '.manifest_list' do
5
- let(:manifest) do
6
- double(
7
- AppArchetype::Template::Manifest,
8
- name: 'test_manifest',
9
- version: '1.0.0'
10
- )
11
- end
12
- let(:manifest_list_row) { ['test_manifest', '1.0.0'] }
13
-
14
- let(:presenter) { double(CliFormat::Presenter) }
15
- let(:manifests) { [manifest, manifest] }
16
-
17
- before do
18
- allow(presenter).to receive(:show)
19
- allow(subject).to receive(:table).and_return(presenter)
20
-
21
- described_class.manifest_list(manifests)
22
- end
23
-
24
- it 'builds table presenter' do
25
- expect(subject).to have_received(:table).with(
26
- header: AppArchetype::CLI::Presenters::RESULT_HEADER,
27
- data: [manifest_list_row, manifest_list_row]
28
- )
29
- end
30
-
31
- it 'shows table' do
32
- expect(presenter).to have_received(:show)
33
- end
34
- end
35
-
36
- describe '.variable_list' do
37
- let(:variable) do
38
- double(
39
- AppArchetype::Template::Variable,
40
- name: 'foo',
41
- description: 'a foo',
42
- default: 'yolo',
43
- value: 'bar'
44
- )
45
- end
46
- let(:variable_row) { ['foo', 'a foo', 'yolo'] }
47
-
48
- let(:presenter) { double(CliFormat::Presenter) }
49
- let(:variables) { [variable, variable] }
50
-
51
- before do
52
- allow(presenter).to receive(:show)
53
- allow(subject).to receive(:table).and_return(presenter)
54
-
55
- described_class.variable_list(variables)
56
- end
57
-
58
- it 'builds table presenter' do
59
- expect(subject).to have_received(:table).with(
60
- header: AppArchetype::CLI::Presenters::VARIABLE_HEADER,
61
- data: [variable_row, variable_row]
62
- )
63
- end
64
-
65
- it 'shows table' do
66
- expect(presenter).to have_received(:show)
67
- end
68
- end
69
-
70
- describe '.validation_results' do
71
- let(:results) do
72
- [
73
- 'something went wrong',
74
- 'something went wrong'
75
- ]
76
- end
77
-
78
- let(:result_row) { ['something went wrong'] }
79
- let(:presenter) { double(CliFormat::Presenter) }
80
-
81
- before do
82
- allow(presenter).to receive(:show)
83
- allow(subject).to receive(:table).and_return(presenter)
84
-
85
- described_class.validation_result(results)
86
- end
87
-
88
- it 'builds table presenter' do
89
- expect(subject).to have_received(:table).with(
90
- header: AppArchetype::CLI::Presenters::VALIDATION_HEADER,
91
- data: [result_row, result_row]
92
- )
93
- end
94
-
95
- it 'shows table' do
96
- expect(presenter).to have_received(:show)
97
- end
98
- end
99
- end
1
+ # require 'spec_helper'
2
+
3
+ # RSpec.xdescribe AppArchetype::CLI::Presenters do
4
+ # describe '.manifest_list' do
5
+ # let(:manifest) do
6
+ # double(
7
+ # AppArchetype::Template::Manifest,
8
+ # name: 'test_manifest',
9
+ # version: '1.0.0'
10
+ # )
11
+ # end
12
+ # let(:manifest_list_row) { ['test_manifest', '1.0.0'] }
13
+
14
+ # let(:presenter) { double(CliFormat::Presenter) }
15
+ # let(:manifests) { [manifest, manifest] }
16
+
17
+ # before do
18
+ # allow(presenter).to receive(:show)
19
+ # allow(subject).to receive(:table).and_return(presenter)
20
+
21
+ # described_class.manifest_list(manifests)
22
+ # end
23
+
24
+ # it 'builds table presenter' do
25
+ # expect(subject).to have_received(:table).with(
26
+ # header: AppArchetype::CLI::Presenters::RESULT_HEADER,
27
+ # data: [manifest_list_row, manifest_list_row]
28
+ # )
29
+ # end
30
+
31
+ # it 'shows table' do
32
+ # expect(presenter).to have_received(:show)
33
+ # end
34
+ # end
35
+
36
+ # describe '.variable_list' do
37
+ # let(:variable) do
38
+ # double(
39
+ # AppArchetype::Template::Variable,
40
+ # name: 'foo',
41
+ # description: 'a foo',
42
+ # default: 'yolo',
43
+ # value: 'bar'
44
+ # )
45
+ # end
46
+ # let(:variable_row) { ['foo', 'a foo', 'yolo'] }
47
+
48
+ # let(:presenter) { double(CliFormat::Presenter) }
49
+ # let(:variables) { [variable, variable] }
50
+
51
+ # before do
52
+ # allow(presenter).to receive(:show)
53
+ # allow(subject).to receive(:table).and_return(presenter)
54
+
55
+ # described_class.variable_list(variables)
56
+ # end
57
+
58
+ # it 'builds table presenter' do
59
+ # expect(subject).to have_received(:table).with(
60
+ # header: AppArchetype::CLI::Presenters::VARIABLE_HEADER,
61
+ # data: [variable_row, variable_row]
62
+ # )
63
+ # end
64
+
65
+ # it 'shows table' do
66
+ # expect(presenter).to have_received(:show)
67
+ # end
68
+ # end
69
+
70
+ # describe '.validation_results' do
71
+ # let(:results) do
72
+ # [
73
+ # 'something went wrong',
74
+ # 'something went wrong'
75
+ # ]
76
+ # end
77
+
78
+ # let(:result_row) { ['something went wrong'] }
79
+ # let(:presenter) { double(CliFormat::Presenter) }
80
+
81
+ # before do
82
+ # allow(presenter).to receive(:show)
83
+ # allow(subject).to receive(:table).and_return(presenter)
84
+
85
+ # described_class.validation_result(results)
86
+ # end
87
+
88
+ # it 'builds table presenter' do
89
+ # expect(subject).to have_received(:table).with(
90
+ # header: AppArchetype::CLI::Presenters::VALIDATION_HEADER,
91
+ # data: [result_row, result_row]
92
+ # )
93
+ # end
94
+
95
+ # it 'shows table' do
96
+ # expect(presenter).to have_received(:show)
97
+ # end
98
+ # end
99
+ # end