opto 1.4.0
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 +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +18 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +21 -0
- data/README.md +407 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/opto.rb +51 -0
- data/lib/opto/extensions/hash_string_or_symbol_key.rb +18 -0
- data/lib/opto/extensions/snake_case.rb +22 -0
- data/lib/opto/group.rb +112 -0
- data/lib/opto/option.rb +298 -0
- data/lib/opto/resolver.rb +65 -0
- data/lib/opto/resolvers/default.rb +10 -0
- data/lib/opto/resolvers/environment_variable.rb +25 -0
- data/lib/opto/resolvers/file_content.rb +32 -0
- data/lib/opto/resolvers/random_number.rb +35 -0
- data/lib/opto/resolvers/random_string.rb +84 -0
- data/lib/opto/resolvers/random_uuid.rb +15 -0
- data/lib/opto/setter.rb +66 -0
- data/lib/opto/setters/environment_variable.rb +40 -0
- data/lib/opto/type.rb +148 -0
- data/lib/opto/types/boolean.rb +57 -0
- data/lib/opto/types/enum.rb +107 -0
- data/lib/opto/types/integer.rb +47 -0
- data/lib/opto/types/string.rb +71 -0
- data/lib/opto/types/uri.rb +36 -0
- data/lib/opto/version.rb +3 -0
- data/opto.gemspec +24 -0
- metadata +119 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative '../type'
|
2
|
+
require 'opto/extensions/snake_case'
|
3
|
+
require 'opto/extensions/hash_string_or_symbol_key'
|
4
|
+
|
5
|
+
if RUBY_VERSION < '2.1'
|
6
|
+
using Opto::Extension::SnakeCase
|
7
|
+
using Opto::Extension::HashStringOrSymbolKey
|
8
|
+
end
|
9
|
+
|
10
|
+
module Opto
|
11
|
+
module Types
|
12
|
+
# A boolean value.
|
13
|
+
#
|
14
|
+
# Options:
|
15
|
+
# :truthy an array of strings / values that are converted to True.
|
16
|
+
# :nil_is by default false
|
17
|
+
# :blank_is by default false too
|
18
|
+
# :as by default outputs a string. integer outputs a number, true_or_nil outputs true or nil. set to nil to just output whatever is in :true and :false
|
19
|
+
# :true says "true" by default when outputting a string
|
20
|
+
# :false says "false" by default when outputting a string
|
21
|
+
class Boolean < Opto::Type
|
22
|
+
using Opto::Extension::HashStringOrSymbolKey unless RUBY_VERSION < '2.1'
|
23
|
+
|
24
|
+
OPTIONS = {
|
25
|
+
truthy: ['true', 'yes', '1', 'on', 'enabled', 'enable'],
|
26
|
+
nil_is: false,
|
27
|
+
blank_is: false,
|
28
|
+
false: 'false',
|
29
|
+
true: 'true',
|
30
|
+
as: 'string'
|
31
|
+
}
|
32
|
+
|
33
|
+
sanitizer :to_bool do |value|
|
34
|
+
if value.nil?
|
35
|
+
options[:nil_is]
|
36
|
+
elsif value.kind_of?(TrueClass) || value.kind_of?(FalseClass)
|
37
|
+
value
|
38
|
+
elsif value.to_s.strip == ''
|
39
|
+
options[:blank_is]
|
40
|
+
else
|
41
|
+
options[:truthy].include?(value.to_s.strip.downcase)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
sanitizer :output do |value|
|
46
|
+
case options[:as].to_s.strip.downcase
|
47
|
+
when 'integer'
|
48
|
+
value ? (options[:true].kind_of?(Fixnum) ? options[:true] : 1) : (options[:false].kind_of?(Fixnum) ? options[:false] : 0)
|
49
|
+
when 'boolean'
|
50
|
+
value
|
51
|
+
else
|
52
|
+
value ? options[:true] : options[:false]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require_relative '../type'
|
2
|
+
require 'opto/extensions/snake_case'
|
3
|
+
require 'opto/extensions/hash_string_or_symbol_key'
|
4
|
+
|
5
|
+
if RUBY_VERSION < '2.1'
|
6
|
+
using Opto::Extension::SnakeCase
|
7
|
+
using Opto::Extension::HashStringOrSymbolKey
|
8
|
+
end
|
9
|
+
|
10
|
+
module Opto
|
11
|
+
module Types
|
12
|
+
# A list of possible values
|
13
|
+
#
|
14
|
+
# :options - a list of possible values for this enum
|
15
|
+
# :can_be_other - set to true if the value can be outside of the value list in options
|
16
|
+
# :in - when "can be other" is defined, this can be used to define an extra set of possible values
|
17
|
+
#
|
18
|
+
# @example Shorthand option list
|
19
|
+
# Opto::Option.new(
|
20
|
+
# name: 'foo',
|
21
|
+
# type: 'enum',
|
22
|
+
# options:
|
23
|
+
# - foo
|
24
|
+
# - bar
|
25
|
+
# - cat
|
26
|
+
# can_be_other: true
|
27
|
+
# )
|
28
|
+
#
|
29
|
+
# @example Detailed option list
|
30
|
+
# Opto::Option.new(
|
31
|
+
# name: 'foo',
|
32
|
+
# type: 'enum',
|
33
|
+
# options:
|
34
|
+
# - value: cat
|
35
|
+
# label: Cat
|
36
|
+
# description: A four legged ball of fur
|
37
|
+
# - value: dog
|
38
|
+
# label: Dog
|
39
|
+
# description: A friendly furry creature with a tail, says 'woof'
|
40
|
+
# )
|
41
|
+
class Enum < Opto::Type
|
42
|
+
using Opto::Extension::HashStringOrSymbolKey unless RUBY_VERSION < '2.1'
|
43
|
+
|
44
|
+
OPTIONS = {
|
45
|
+
options: [],
|
46
|
+
can_be_other: false,
|
47
|
+
in: []
|
48
|
+
}
|
49
|
+
|
50
|
+
def initialize(options={})
|
51
|
+
opts = normalize_opts(options.delete(:options))
|
52
|
+
super(options)
|
53
|
+
@options[:options] = opts
|
54
|
+
end
|
55
|
+
|
56
|
+
validator :options do |value|
|
57
|
+
if options[:options].nil? || options[:options].empty?
|
58
|
+
raise RuntimeError, "No options defined for enum"
|
59
|
+
elsif options[:options].map {|o| o[:value]}.uniq.size != options[:options].size
|
60
|
+
raise RuntimeError, "Duplicate values in enum option list"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
validator :in do |value|
|
65
|
+
return nil if options[:can_be_other]
|
66
|
+
if options[:in] && !options[:in].empty?
|
67
|
+
"Value is not one of #{options[:in].join(', ')}" unless options[:in].include?(value)
|
68
|
+
else
|
69
|
+
"Value is not one of the options" unless options[:options].map { |o| o[:value] }.include?(value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def normalize_opts(options)
|
74
|
+
case options
|
75
|
+
when Hash
|
76
|
+
options.each_with_object([]) do |(key, value), array|
|
77
|
+
array << { value: key, label: key, description: value }
|
78
|
+
end
|
79
|
+
when Array
|
80
|
+
case options.first
|
81
|
+
when Hash
|
82
|
+
options.each do |opt|
|
83
|
+
if opt[:value].nil? || opt[:description].nil?
|
84
|
+
raise TypeError, "Option definition requires value and description and can have label when using hash syntax"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
options
|
88
|
+
when ::String, Fixnum
|
89
|
+
options.map do |opt|
|
90
|
+
{ value: opt, description: opt, label: opt }
|
91
|
+
end
|
92
|
+
when NilClass
|
93
|
+
[]
|
94
|
+
else
|
95
|
+
raise TypeError, "Invalid format for enum option list definition"
|
96
|
+
end
|
97
|
+
when NilClass
|
98
|
+
[]
|
99
|
+
else
|
100
|
+
raise TypeError, "Invalid format for enum option list definition"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative '../type'
|
2
|
+
require 'opto/extensions/snake_case'
|
3
|
+
require 'opto/extensions/hash_string_or_symbol_key'
|
4
|
+
|
5
|
+
if RUBY_VERSION < '2.1'
|
6
|
+
using Opto::Extension::SnakeCase
|
7
|
+
using Opto::Extension::HashStringOrSymbolKey
|
8
|
+
end
|
9
|
+
|
10
|
+
module Opto
|
11
|
+
module Types
|
12
|
+
# A number.
|
13
|
+
#
|
14
|
+
# Options
|
15
|
+
# :min - minimum allowed value (default 0, can be negative)
|
16
|
+
# :max - maximum allowed value
|
17
|
+
# :nil_is_zero : set to true if you want to turn a null value into 0
|
18
|
+
class Integer < Opto::Type
|
19
|
+
using Opto::Extension::HashStringOrSymbolKey unless RUBY_VERSION < '2.1'
|
20
|
+
|
21
|
+
OPTIONS = {
|
22
|
+
min: 0,
|
23
|
+
max: nil,
|
24
|
+
nil_is_zero: false
|
25
|
+
}
|
26
|
+
|
27
|
+
sanitizer :to_i do |value|
|
28
|
+
value.nil? ? (options[:nil_is_zero] ? 0 : nil) : value.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
validator :min do |value|
|
32
|
+
return nil if value.nil?
|
33
|
+
if options[:min] && value < options[:min]
|
34
|
+
"Too small. Minimum value is #{options[:min_length]}, Value is #{value}."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
validator :max do |value|
|
39
|
+
return nil if value.nil?
|
40
|
+
if options[:max] && value > options[:max]
|
41
|
+
"Too large. Maximum value is #{options[:max]}, Value is #{value}."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative '../type'
|
2
|
+
require 'base64'
|
3
|
+
require 'opto/extensions/snake_case'
|
4
|
+
require 'opto/extensions/hash_string_or_symbol_key'
|
5
|
+
|
6
|
+
if RUBY_VERSION < '2.1'
|
7
|
+
using Opto::Extension::SnakeCase
|
8
|
+
using Opto::Extension::HashStringOrSymbolKey
|
9
|
+
end
|
10
|
+
|
11
|
+
module Opto
|
12
|
+
module Types
|
13
|
+
# A string
|
14
|
+
#
|
15
|
+
# Options:
|
16
|
+
# - min_length: minimum lenght
|
17
|
+
# - max_length: maximum length
|
18
|
+
# - empty_is_nil: an empty string will be replaced with nil
|
19
|
+
# - encode_64: set to true if you want the final value to be base64 encoded representation
|
20
|
+
# - decode_64: set to true if your string is in base64 and you want to convert to plain text
|
21
|
+
# - upcase: set to true to upcase the string
|
22
|
+
# - downcase: set to true to downcase the string
|
23
|
+
# - strip: set to true to remove leading and trailing whitespace
|
24
|
+
# - chomp: set to true to remove trailing linefeed
|
25
|
+
# - capitalize: set to true to upcase the first letter
|
26
|
+
class String < Opto::Type
|
27
|
+
using Opto::Extension::HashStringOrSymbolKey unless RUBY_VERSION < '2.1'
|
28
|
+
|
29
|
+
TRANSFORMATIONS = [ :upcase, :downcase, :strip, :chomp, :capitalize ]
|
30
|
+
|
31
|
+
OPTIONS = {
|
32
|
+
min_length: nil,
|
33
|
+
max_length: nil,
|
34
|
+
empty_is_nil: true,
|
35
|
+
encode_64: false,
|
36
|
+
decode_64: false
|
37
|
+
}.merge(Hash[*TRANSFORMATIONS.flat_map {|tr| [tr, false]}])
|
38
|
+
|
39
|
+
|
40
|
+
sanitizer :encode_64 do |value|
|
41
|
+
(options[:encode_64] && value) ? Base64.encode64(value) : value
|
42
|
+
end
|
43
|
+
|
44
|
+
sanitizer :decode_64 do |value|
|
45
|
+
(options[:decode_64] && value) ? Base64.decode64(value) : value
|
46
|
+
end
|
47
|
+
|
48
|
+
TRANSFORMATIONS.each do |transform|
|
49
|
+
sanitizer transform do |value|
|
50
|
+
(options[transform] && value.respond_to?(transform)) ? value.send(transform) : value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
sanitizer :empty_is_nil do |value|
|
55
|
+
(options[:empty_is_nil] && value.to_s.strip.empty?) ? nil : value.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
validator :min_length do |value|
|
59
|
+
if options[:min_length] && value.length < options[:min_length]
|
60
|
+
"Too short. Minimum length is #{options[:min_length]}, length is #{value.length}."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
validator :max_length do |value|
|
65
|
+
if options[:max_length] && value.length > options[:max_length]
|
66
|
+
"Too long. Maximum length is #{options[:max_length]}, length is #{value.length}."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '../type'
|
2
|
+
require 'uri'
|
3
|
+
require 'opto/extensions/snake_case'
|
4
|
+
require 'opto/extensions/hash_string_or_symbol_key'
|
5
|
+
|
6
|
+
if RUBY_VERSION < '2.1'
|
7
|
+
using Opto::Extension::SnakeCase
|
8
|
+
using Opto::Extension::HashStringOrSymbolKey
|
9
|
+
end
|
10
|
+
|
11
|
+
module Opto
|
12
|
+
module Types
|
13
|
+
# An uri/url.
|
14
|
+
#
|
15
|
+
# Options:
|
16
|
+
# schemes: an array of allowed schemes, such as ['http', 'https', 'file']
|
17
|
+
class Uri < Opto::Type
|
18
|
+
using Opto::Extension::HashStringOrSymbolKey unless RUBY_VERSION < '2.1'
|
19
|
+
|
20
|
+
OPTIONS = {
|
21
|
+
schemes: [ 'http', 'https' ]
|
22
|
+
}
|
23
|
+
|
24
|
+
validator :scheme do |value|
|
25
|
+
return nil if options[:schemes].nil? || options[:schemes].empty?
|
26
|
+
scheme = uri(value).scheme
|
27
|
+
return nil if options[:schemes].include?(scheme)
|
28
|
+
"Uri scheme '#{scheme}' not allowed, allowed schemes: #{options[:schemes].join(', ')}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def uri(value)
|
32
|
+
URI.parse(value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/opto/version.rb
ADDED
data/opto.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'opto/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "opto"
|
8
|
+
spec.version = Opto::VERSION
|
9
|
+
spec.authors = ["Kimmo Lehto"]
|
10
|
+
spec.email = ["info@kontena.io"]
|
11
|
+
|
12
|
+
spec.summary = "Create validatable and resolvable options from hashes"
|
13
|
+
spec.description = "Example: Opto.new(type: :string, name: 'foo, min_length: 20, from: { env: 'FOO' }).value"
|
14
|
+
spec.homepage = "https://github.com/kontena/opto"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "bin"
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kimmo Lehto
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: 'Example: Opto.new(type: :string, name: ''foo, min_length: 20, from:
|
56
|
+
{ env: ''FOO'' }).value'
|
57
|
+
email:
|
58
|
+
- info@kontena.io
|
59
|
+
executables:
|
60
|
+
- console
|
61
|
+
- setup
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".gitignore"
|
66
|
+
- ".rspec"
|
67
|
+
- ".travis.yml"
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- bin/console
|
73
|
+
- bin/setup
|
74
|
+
- lib/opto.rb
|
75
|
+
- lib/opto/extensions/hash_string_or_symbol_key.rb
|
76
|
+
- lib/opto/extensions/snake_case.rb
|
77
|
+
- lib/opto/group.rb
|
78
|
+
- lib/opto/option.rb
|
79
|
+
- lib/opto/resolver.rb
|
80
|
+
- lib/opto/resolvers/default.rb
|
81
|
+
- lib/opto/resolvers/environment_variable.rb
|
82
|
+
- lib/opto/resolvers/file_content.rb
|
83
|
+
- lib/opto/resolvers/random_number.rb
|
84
|
+
- lib/opto/resolvers/random_string.rb
|
85
|
+
- lib/opto/resolvers/random_uuid.rb
|
86
|
+
- lib/opto/setter.rb
|
87
|
+
- lib/opto/setters/environment_variable.rb
|
88
|
+
- lib/opto/type.rb
|
89
|
+
- lib/opto/types/boolean.rb
|
90
|
+
- lib/opto/types/enum.rb
|
91
|
+
- lib/opto/types/integer.rb
|
92
|
+
- lib/opto/types/string.rb
|
93
|
+
- lib/opto/types/uri.rb
|
94
|
+
- lib/opto/version.rb
|
95
|
+
- opto.gemspec
|
96
|
+
homepage: https://github.com/kontena/opto
|
97
|
+
licenses: []
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 2.4.5
|
116
|
+
signing_key:
|
117
|
+
specification_version: 4
|
118
|
+
summary: Create validatable and resolvable options from hashes
|
119
|
+
test_files: []
|