jimmy 0.5.5
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 +11 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/LICENSE +13 -0
- data/README.md +151 -0
- data/Rakefile +4 -0
- data/circle.yml +11 -0
- data/jimmy.gemspec +28 -0
- data/lib/jimmy.rb +20 -0
- data/lib/jimmy/combination.rb +34 -0
- data/lib/jimmy/definitions.rb +38 -0
- data/lib/jimmy/domain.rb +111 -0
- data/lib/jimmy/link.rb +93 -0
- data/lib/jimmy/reference.rb +39 -0
- data/lib/jimmy/schema.rb +114 -0
- data/lib/jimmy/schema_creation.rb +121 -0
- data/lib/jimmy/schema_type.rb +100 -0
- data/lib/jimmy/schema_types.rb +42 -0
- data/lib/jimmy/schema_types/array.rb +30 -0
- data/lib/jimmy/schema_types/boolean.rb +6 -0
- data/lib/jimmy/schema_types/integer.rb +8 -0
- data/lib/jimmy/schema_types/null.rb +6 -0
- data/lib/jimmy/schema_types/number.rb +34 -0
- data/lib/jimmy/schema_types/object.rb +45 -0
- data/lib/jimmy/schema_types/string.rb +40 -0
- data/lib/jimmy/symbol_array.rb +17 -0
- data/lib/jimmy/transform_keys.rb +39 -0
- data/lib/jimmy/type_reference.rb +14 -0
- data/lib/jimmy/validation_error.rb +20 -0
- data/lib/jimmy/version.rb +3 -0
- metadata +144 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require_relative 'schema_type'
|
4
|
+
require_relative 'schema_creation'
|
5
|
+
|
6
|
+
module Jimmy
|
7
|
+
module SchemaTypes
|
8
|
+
|
9
|
+
@types = {}
|
10
|
+
@dsls = {}
|
11
|
+
@nested_handlers = {}
|
12
|
+
@compilers = {}
|
13
|
+
|
14
|
+
class << self
|
15
|
+
extend Forwardable
|
16
|
+
|
17
|
+
delegate %i[each keys values key?] => :@types
|
18
|
+
|
19
|
+
attr_reader :dsls, :nested_handlers, :compilers
|
20
|
+
|
21
|
+
def [](type_name)
|
22
|
+
@types[type_name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def register(type_class)
|
26
|
+
type_name = type_class.name[/\w+$/].downcase.to_sym
|
27
|
+
dsl_class = Class.new(type_class.superclass::DSL)
|
28
|
+
type_class.const_set :DSL, dsl_class
|
29
|
+
@dsls[type_name] = dsl_class
|
30
|
+
@types[type_name] = type_class
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
Dir[ROOT + 'lib/jimmy/schema_types/*.rb'].each do |path|
|
36
|
+
require path
|
37
|
+
end
|
38
|
+
|
39
|
+
nested_handlers.each { |klass, handler| SchemaCreation.apply_to klass::DSL, &handler }
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Jimmy
|
2
|
+
class SchemaTypes::Array < SchemaType
|
3
|
+
register!
|
4
|
+
|
5
|
+
trait :min_items
|
6
|
+
trait :max_items
|
7
|
+
trait(:unique) { attrs[:unique_items] = true }
|
8
|
+
trait Range do |range|
|
9
|
+
min, max = [range.first, range.last].sort
|
10
|
+
min_items min
|
11
|
+
max_items max
|
12
|
+
end
|
13
|
+
trait(Integer) { |value| min_items value; max_items value }
|
14
|
+
|
15
|
+
nested do |schema|
|
16
|
+
(attrs[:items] ||= []) << schema
|
17
|
+
end
|
18
|
+
|
19
|
+
compile do |hash|
|
20
|
+
hash.merge! camelize_attrs(%i[min_items max_items unique_items])
|
21
|
+
items = attrs[:items] || []
|
22
|
+
if items.length > 1
|
23
|
+
hash['items'] = {'anyOf' => items.map(&:compile)}
|
24
|
+
elsif items.length == 1
|
25
|
+
hash['items'] = items.first.compile
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Jimmy
|
2
|
+
class SchemaTypes::Number < SchemaType
|
3
|
+
register!
|
4
|
+
|
5
|
+
trait :multiple_of
|
6
|
+
trait :minimum
|
7
|
+
trait :maximum
|
8
|
+
trait(:<) { |value| maximum value; attrs[:exclusive_maximum] = true; self }
|
9
|
+
trait(:<=) { |value| maximum value; attrs[:exclusive_maximum] = nil; self }
|
10
|
+
trait(:>) { |value| minimum value; attrs[:exclusive_minimum] = true; self }
|
11
|
+
trait(:>=) { |value| minimum value; attrs[:exclusive_minimum] = nil; self }
|
12
|
+
trait(:enum) do |*values|
|
13
|
+
attrs[:enum] ||= []
|
14
|
+
attrs[:enum] |= values.flatten
|
15
|
+
end
|
16
|
+
trait(Numeric, Array) { |value| enum value }
|
17
|
+
trait(Range) do |range|
|
18
|
+
if range.first <= range.last
|
19
|
+
minimum range.first
|
20
|
+
maximum range.last
|
21
|
+
attrs[:exclusive_maximum] ||= range.exclude_end? || nil
|
22
|
+
else
|
23
|
+
minimum range.last
|
24
|
+
maximum range.first
|
25
|
+
attrs[:exclusive_minimum] ||= range.exclude_end? || nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
compile do |hash|
|
30
|
+
hash.merge! camelize_attrs(%i[minimum maximum exclusive_minimum exclusive_maximum multiple_of enum])
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative '../transform_keys'
|
2
|
+
|
3
|
+
module Jimmy
|
4
|
+
class SchemaTypes::Object < SchemaType
|
5
|
+
register!
|
6
|
+
|
7
|
+
trait :require do |*required_keys|
|
8
|
+
if required_keys == [0]
|
9
|
+
attrs[:required] = SymbolArray.new
|
10
|
+
else
|
11
|
+
attrs[:required] ||= SymbolArray.new
|
12
|
+
attrs[:required] |= required_keys.flatten.map(&:to_s).uniq
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
trait :all do
|
17
|
+
SymbolArray.new(attrs[:properties].keys.select { |x| x.is_a? Symbol })
|
18
|
+
end
|
19
|
+
|
20
|
+
trait(:none) { 0 }
|
21
|
+
|
22
|
+
trait(:allow_additional) { attrs[:additional_properties] = true }
|
23
|
+
|
24
|
+
nested do |schema, property_name|
|
25
|
+
(attrs[:properties] ||= {})[TransformKeys.transformer.transform(property_name, domain.options[:transform_keys])] = schema
|
26
|
+
end
|
27
|
+
|
28
|
+
compile do |hash|
|
29
|
+
(attrs[:properties] || {}).each do |key, value|
|
30
|
+
collection, key =
|
31
|
+
if key.is_a? Regexp
|
32
|
+
['patternProperties', key.inspect.gsub(%r`^/|/[a-z]*$`, '')]
|
33
|
+
else
|
34
|
+
['properties', key.to_s]
|
35
|
+
end
|
36
|
+
hash[collection] ||= {}
|
37
|
+
hash[collection][key] = value.compile
|
38
|
+
end
|
39
|
+
required = attrs[:required]
|
40
|
+
hash['required'] = required.to_a if required && !required.empty?
|
41
|
+
hash['additionalProperties'] = !!attrs[:additional_properties]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Jimmy
|
2
|
+
class SchemaTypes::String < SchemaType
|
3
|
+
register!
|
4
|
+
|
5
|
+
trait :min_length
|
6
|
+
trait :max_length
|
7
|
+
trait(:pattern) { |regex| attrs[:pattern] = regex.is_a?(Regexp) ? regex.inspect.gsub(%r`^/|/[a-z]*$`, '') : regex }
|
8
|
+
trait(:format) { |value| attrs[:format] = value.to_s.gsub('_', '-') }
|
9
|
+
%i[
|
10
|
+
date_time
|
11
|
+
email
|
12
|
+
hostname
|
13
|
+
ipv4
|
14
|
+
ipv6
|
15
|
+
uri
|
16
|
+
].each { |k| trait(k) { format k } }
|
17
|
+
trait(:enum) do |*values|
|
18
|
+
attrs[:enum] ||= []
|
19
|
+
attrs[:enum] |= values.flatten.map(&:to_s)
|
20
|
+
end
|
21
|
+
trait(Regexp) { |regex| pattern regex }
|
22
|
+
trait Range do |value|
|
23
|
+
variation = value.exclude_end? ? 1 : 0
|
24
|
+
if value.first < value.last
|
25
|
+
attrs[:min_length] = value.first
|
26
|
+
attrs[:max_length] = value.last - variation
|
27
|
+
else
|
28
|
+
attrs[:max_length] = value.first
|
29
|
+
attrs[:min_length] = value.last + variation
|
30
|
+
end
|
31
|
+
end
|
32
|
+
trait(Integer) { |value| min_length value; max_length value }
|
33
|
+
trait(Array) { |value| enum value }
|
34
|
+
|
35
|
+
compile do |hash|
|
36
|
+
hash.merge! camelize_attrs(%i[min_length max_length pattern enum format])
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Jimmy
|
2
|
+
class SymbolArray < Array
|
3
|
+
|
4
|
+
def initialize(*args)
|
5
|
+
super args.flatten.map(&:to_s)
|
6
|
+
end
|
7
|
+
|
8
|
+
%i(<< push unshift).each do |method|
|
9
|
+
define_method(method) { |*args| super *args.map(&:to_s) }
|
10
|
+
end
|
11
|
+
|
12
|
+
%i(+ - | &).each do |method|
|
13
|
+
define_method(method) { |*args| SymbolArray.new(super args.flatten.map(&:to_s)) }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Jimmy
|
2
|
+
module TransformKeys
|
3
|
+
def camel_upper(str)
|
4
|
+
camel_lower(str).sub(/\A(.)/) { $1.upcase }
|
5
|
+
end
|
6
|
+
|
7
|
+
def camel_lower(str)
|
8
|
+
str.gsub(/[-_\s]+(.)/) { $1.upcase }
|
9
|
+
end
|
10
|
+
|
11
|
+
class Transformer
|
12
|
+
include TransformKeys
|
13
|
+
|
14
|
+
def cache(method)
|
15
|
+
(@cache ||= {})[method] ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def transform(sym, method)
|
19
|
+
if method && sym.is_a?(Symbol)
|
20
|
+
cache(method)[sym] ||= __send__(method, sym.to_s).to_sym
|
21
|
+
else
|
22
|
+
sym
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def transform_ref(str, method)
|
27
|
+
if method
|
28
|
+
str.sub(/#(.+)/) { '#' << $1.split('/').map { |part| __send__ method, part }.join('/') }
|
29
|
+
else
|
30
|
+
str
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.transformer
|
36
|
+
@transformer ||= Transformer.new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Jimmy
|
2
|
+
class TypeReference < Reference
|
3
|
+
attr_reader :type
|
4
|
+
|
5
|
+
def initialize(type, domain, *args)
|
6
|
+
@type = type
|
7
|
+
uri = domain.root + "types/#{type}.json#"
|
8
|
+
path = uri.path.dup
|
9
|
+
path << '?' << uri.query if uri.query
|
10
|
+
path << '#' << uri.fragment if uri.fragment
|
11
|
+
super path, domain, *args
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Jimmy
|
4
|
+
class ValidationError < StandardError
|
5
|
+
|
6
|
+
attr_reader :schema, :data, :errors
|
7
|
+
|
8
|
+
def initialize(schema, data, errors)
|
9
|
+
@schema = schema
|
10
|
+
@data = data
|
11
|
+
@errors = errors.map do |info|
|
12
|
+
OpenStruct.new(
|
13
|
+
property: info[:fragment][2..-1],
|
14
|
+
message: info[:message].gsub(/ in schema \S+$/, ''),
|
15
|
+
aspect: info[:failed_attribute]
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jimmy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Neil E. Pearson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json-schema
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.9'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: diff_matcher
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.7'
|
83
|
+
description: Jimmy makes it a snap to compose detailed JSON schema documents.
|
84
|
+
email:
|
85
|
+
- neil.pearson@orionvm.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".ruby-version"
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- circle.yml
|
97
|
+
- jimmy.gemspec
|
98
|
+
- lib/jimmy.rb
|
99
|
+
- lib/jimmy/combination.rb
|
100
|
+
- lib/jimmy/definitions.rb
|
101
|
+
- lib/jimmy/domain.rb
|
102
|
+
- lib/jimmy/link.rb
|
103
|
+
- lib/jimmy/reference.rb
|
104
|
+
- lib/jimmy/schema.rb
|
105
|
+
- lib/jimmy/schema_creation.rb
|
106
|
+
- lib/jimmy/schema_type.rb
|
107
|
+
- lib/jimmy/schema_types.rb
|
108
|
+
- lib/jimmy/schema_types/array.rb
|
109
|
+
- lib/jimmy/schema_types/boolean.rb
|
110
|
+
- lib/jimmy/schema_types/integer.rb
|
111
|
+
- lib/jimmy/schema_types/null.rb
|
112
|
+
- lib/jimmy/schema_types/number.rb
|
113
|
+
- lib/jimmy/schema_types/object.rb
|
114
|
+
- lib/jimmy/schema_types/string.rb
|
115
|
+
- lib/jimmy/symbol_array.rb
|
116
|
+
- lib/jimmy/transform_keys.rb
|
117
|
+
- lib/jimmy/type_reference.rb
|
118
|
+
- lib/jimmy/validation_error.rb
|
119
|
+
- lib/jimmy/version.rb
|
120
|
+
homepage: https://github.com/hx/jimmy
|
121
|
+
licenses:
|
122
|
+
- Apache License, Version 2.0
|
123
|
+
metadata: {}
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 2.6.8
|
141
|
+
signing_key:
|
142
|
+
specification_version: 4
|
143
|
+
summary: Jimmy the JSON Schema DSL
|
144
|
+
test_files: []
|