Skip to content

Commit 828358f

Browse files
committed
- Validate the entire config prior to generating
1 parent 9f3ff81 commit 828358f

File tree

19 files changed

+196
-94
lines changed

19 files changed

+196
-94
lines changed

lib/bashly/config_validator.rb

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
module Bashly
2+
class ConfigValidator
3+
attr_reader :data
4+
5+
def initialize(data)
6+
@data = data
7+
end
8+
9+
def validate
10+
assert_command "root", data
11+
end
12+
13+
private
14+
15+
def assert(valid, message)
16+
raise ConfigurationError, message unless valid
17+
end
18+
19+
def refute(invalid, message)
20+
assert !invalid, message
21+
end
22+
23+
def assert_string(key, value)
24+
assert value.is_a?(String), "#{key} must be a string"
25+
end
26+
27+
def assert_boolean(key, value)
28+
assert [true, false, nil].include?(value), "#{key} must be a boolean"
29+
end
30+
31+
def assert_array(key, value, of: nil)
32+
return unless value
33+
assert value.is_a?(Array), "#{key} must be an array"
34+
if of
35+
value.each_with_index do |val, i|
36+
send "assert_#{of}".to_sym, "#{key}[#{i}]", val
37+
end
38+
end
39+
end
40+
41+
def assert_hash(key, value)
42+
assert value.is_a?(Hash), "#{key} must be a hash"
43+
end
44+
45+
def assert_version(key, value)
46+
assert [String, Integer, Float].include?(value.class),
47+
"#{key} must be a string or a number"
48+
end
49+
50+
def assert_catch_all(key, value)
51+
return unless value
52+
assert [TrueClass, String, Hash].include?(value.class),
53+
"#{key} must be a boolean, a string or a hash"
54+
end
55+
56+
def assert_extensible(key, value)
57+
return unless value
58+
assert [TrueClass, String].include?(value.class),
59+
"#{key} must be a boolean or a string"
60+
end
61+
62+
def assert_arg(key, value)
63+
assert_hash key, value
64+
assert_string "#{key}.name", value['name']
65+
assert_string "#{key}.help", value['help'] if value['help']
66+
assert_string "#{key}.default", value['default'] if value['default']
67+
assert_string "#{key}.validate", value['validate'] if value['validate']
68+
assert_boolean "#{key}.required", value['required']
69+
70+
assert_array "#{key}.allowed", value['allowed'], of: :string
71+
end
72+
73+
def assert_flag(key, value)
74+
assert_hash key, value
75+
assert value['short'] || value['long'], "#{key} must have at least one of long or short name"
76+
77+
assert_string "#{key}.long", value['long'] if value['long']
78+
assert_string "#{key}.short", value['short'] if value['short']
79+
assert_string "#{key}.help", value['help'] if value['help']
80+
assert_string "#{key}.arg", value['arg'] if value['arg']
81+
82+
assert_string "#{key}.default", value['default'] if value['default']
83+
assert_string "#{key}.validate", value['validate'] if value['validate']
84+
assert_boolean "#{key}.required", value['required']
85+
86+
assert_array "#{key}.allowed", value['allowed'], of: :string
87+
end
88+
89+
def assert_env_var(key, value)
90+
assert_hash key, value
91+
assert_string "#{key}.name", value['name']
92+
assert_string "#{key}.help", value['help'] if value['help']
93+
assert_string "#{key}.default", value['default'] if value['default']
94+
assert_boolean "#{key}.required", value['required']
95+
end
96+
97+
def assert_command(key, value)
98+
assert_hash key, value
99+
100+
refute value['commands'] && value['args'], "#{key} cannot have both commands and args"
101+
refute value['commands'] && value['flags'], "#{key} cannot have both commands and flags"
102+
103+
assert_string "#{key}.name", value['name']
104+
assert_string "#{key}.short", value['short'] if value['short']
105+
assert_string "#{key}.help", value['help'] if value['help']
106+
assert_string "#{key}.footer", value['footer'] if value['footer']
107+
assert_string "#{key}.group", value['group'] if value['group']
108+
assert_boolean "#{key}.default", value['default']
109+
110+
assert_version "#{key}.version", value['version'] if value['version']
111+
assert_catch_all "#{key}.catch_all", value['catch_all']
112+
assert_extensible "#{key}.extensible", value['extensible']
113+
114+
assert_array "#{key}.args", value['args'], of: :arg
115+
assert_array "#{key}.flags", value['flags'] , of: :flag
116+
assert_array "#{key}.commands", value['commands'], of: :command
117+
assert_array "#{key}.completions", value['completions'], of: :string
118+
assert_array "#{key}.dependencies", value['dependencies'], of: :string
119+
assert_array "#{key}.environment_variables", value['environment_variables'], of: :env_var
120+
assert_array "#{key}.examples", value['examples'], of: :string
121+
end
122+
end
123+
end

lib/bashly/script/argument.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ class Argument < Base
44
def usage_string
55
required ? name.upcase : "[#{name.upcase}]"
66
end
7-
8-
def verify
9-
raise ConfigurationError, "Argument must have a name" unless name
10-
end
117
end
128
end
139
end

lib/bashly/script/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Base
3333
def initialize(options)
3434
raise Error, "Invalid options provided" unless options.respond_to? :keys
3535
@options = options
36-
verify if respond_to? :verify
36+
validate_options if respond_to? :validate_options
3737
end
3838

3939
def optional

lib/bashly/script/command.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,9 @@ def user_lib
213213
end
214214

215215
# Raise an exception if there are some serious issues with the command
216-
# definition.
217-
def verify
218-
verify_commands if commands.any?
219-
raise ConfigurationError, "Command must have a name" unless name
216+
# definition. This is called by Base#initialize.
217+
def validate_options
218+
Bashly::ConfigValidator.new(options).validate
220219
end
221220

222221
# Returns an array of all the args with a whitelist
@@ -229,14 +228,6 @@ def whitelisted_flags
229228
flags.select &:allowed
230229
end
231230

232-
private
233-
234-
def verify_commands
235-
if args.any? or flags.any?
236-
raise ConfigurationError, "Error in the !txtgrn!#{full_name}!txtrst! command.\nThe !txtgrn!commands!txtrst! key cannot be at the same level as the !txtgrn!args!txtrst! or !txtgrn!flags!txtrst! keys."
237-
end
238-
end
239-
240231
end
241232
end
242233
end

lib/bashly/script/environment_variable.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ def usage_string(extended: false)
66
result << strings[:required] if required and extended
77
result.join " "
88
end
9-
10-
def verify
11-
raise ConfigurationError, "EnvironmentVariable must have a name" unless name
12-
end
139
end
1410
end
1511
end

lib/bashly/script/flag.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ def usage_string(extended: false)
2121
result << strings[:required] if required and extended
2222
result.join " "
2323
end
24-
25-
def verify
26-
raise ConfigurationError, "Flag must have a long and/or short property" unless short or long
27-
end
28-
2924
end
3025
end
3126
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#<Bashly::ConfigurationError: root cannot have both commands and args>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#<Bashly::ConfigurationError: root cannot have both commands and flags>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#<Bashly::ConfigurationError: root.extensible must be a boolean or a string>

spec/approvals/validations/nested

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#<Bashly::ConfigurationError: root.commands[0].commands[1].args[1].name must be a string>

0 commit comments

Comments
 (0)