json_skooma 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +22 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +107 -0
  5. data/data/draft-2019-09/README.md +60 -0
  6. data/data/draft-2019-09/hyper-schema.json +26 -0
  7. data/data/draft-2019-09/links.json +91 -0
  8. data/data/draft-2019-09/meta/applicator.json +56 -0
  9. data/data/draft-2019-09/meta/content.json +17 -0
  10. data/data/draft-2019-09/meta/core.json +57 -0
  11. data/data/draft-2019-09/meta/format.json +14 -0
  12. data/data/draft-2019-09/meta/hyper-schema.json +29 -0
  13. data/data/draft-2019-09/meta/meta-data.json +37 -0
  14. data/data/draft-2019-09/meta/validation.json +98 -0
  15. data/data/draft-2019-09/output/hyper-schema.json +62 -0
  16. data/data/draft-2019-09/output/schema.json +86 -0
  17. data/data/draft-2019-09/output/verbose-example.json +130 -0
  18. data/data/draft-2019-09/schema.json +42 -0
  19. data/data/draft-2020-12/README.md +89 -0
  20. data/data/draft-2020-12/adr/README.md +15 -0
  21. data/data/draft-2020-12/archive/hyper-schema.json +28 -0
  22. data/data/draft-2020-12/archive/links.json +93 -0
  23. data/data/draft-2020-12/archive/meta/hyper-schema.json +30 -0
  24. data/data/draft-2020-12/hyper-schema.json +27 -0
  25. data/data/draft-2020-12/links.json +85 -0
  26. data/data/draft-2020-12/meta/applicator.json +48 -0
  27. data/data/draft-2020-12/meta/content.json +17 -0
  28. data/data/draft-2020-12/meta/core.json +51 -0
  29. data/data/draft-2020-12/meta/format-annotation.json +14 -0
  30. data/data/draft-2020-12/meta/format-assertion.json +14 -0
  31. data/data/draft-2020-12/meta/hyper-schema.json +29 -0
  32. data/data/draft-2020-12/meta/meta-data.json +37 -0
  33. data/data/draft-2020-12/meta/unevaluated.json +15 -0
  34. data/data/draft-2020-12/meta/validation.json +98 -0
  35. data/data/draft-2020-12/output/hyper-schema.json +62 -0
  36. data/data/draft-2020-12/output/schema.json +96 -0
  37. data/data/draft-2020-12/output/verbose-example.json +130 -0
  38. data/data/draft-2020-12/schema.json +58 -0
  39. data/lib/json_skooma/dialects/draft201909.rb +137 -0
  40. data/lib/json_skooma/dialects/draft202012.rb +146 -0
  41. data/lib/json_skooma/formatters.rb +135 -0
  42. data/lib/json_skooma/inflector.rb +13 -0
  43. data/lib/json_skooma/json_node.rb +100 -0
  44. data/lib/json_skooma/json_pointer.rb +79 -0
  45. data/lib/json_skooma/json_schema.rb +176 -0
  46. data/lib/json_skooma/keywords/applicator/additional_properties.rb +37 -0
  47. data/lib/json_skooma/keywords/applicator/all_of.rb +25 -0
  48. data/lib/json_skooma/keywords/applicator/any_of.rb +26 -0
  49. data/lib/json_skooma/keywords/applicator/contains.rb +31 -0
  50. data/lib/json_skooma/keywords/applicator/dependent_schemas.rb +35 -0
  51. data/lib/json_skooma/keywords/applicator/else.rb +22 -0
  52. data/lib/json_skooma/keywords/applicator/if.rb +17 -0
  53. data/lib/json_skooma/keywords/applicator/items.rb +36 -0
  54. data/lib/json_skooma/keywords/applicator/not.rb +19 -0
  55. data/lib/json_skooma/keywords/applicator/one_of.rb +35 -0
  56. data/lib/json_skooma/keywords/applicator/pattern_properties.rb +46 -0
  57. data/lib/json_skooma/keywords/applicator/prefix_items.rb +31 -0
  58. data/lib/json_skooma/keywords/applicator/properties.rb +34 -0
  59. data/lib/json_skooma/keywords/applicator/property_names.rb +25 -0
  60. data/lib/json_skooma/keywords/applicator/then.rb +22 -0
  61. data/lib/json_skooma/keywords/base.rb +74 -0
  62. data/lib/json_skooma/keywords/base_annotation.rb +12 -0
  63. data/lib/json_skooma/keywords/content/content_encoding.rb +12 -0
  64. data/lib/json_skooma/keywords/content/content_media_type.rb +12 -0
  65. data/lib/json_skooma/keywords/content/content_schema.rb +19 -0
  66. data/lib/json_skooma/keywords/core/anchor.rb +22 -0
  67. data/lib/json_skooma/keywords/core/comment.rb +12 -0
  68. data/lib/json_skooma/keywords/core/defs.rb +13 -0
  69. data/lib/json_skooma/keywords/core/dynamic_anchor.rb +22 -0
  70. data/lib/json_skooma/keywords/core/dynamic_ref.rb +67 -0
  71. data/lib/json_skooma/keywords/core/id.rb +28 -0
  72. data/lib/json_skooma/keywords/core/ref.rb +35 -0
  73. data/lib/json_skooma/keywords/core/schema.rb +26 -0
  74. data/lib/json_skooma/keywords/core/vocabulary.rb +34 -0
  75. data/lib/json_skooma/keywords/draft_2019_09/additional_items.rb +40 -0
  76. data/lib/json_skooma/keywords/draft_2019_09/items.rb +41 -0
  77. data/lib/json_skooma/keywords/draft_2019_09/recursive_anchor.rb +12 -0
  78. data/lib/json_skooma/keywords/draft_2019_09/recursive_ref.rb +46 -0
  79. data/lib/json_skooma/keywords/draft_2019_09/unevaluated_items.rb +56 -0
  80. data/lib/json_skooma/keywords/format_annotation/format.rb +27 -0
  81. data/lib/json_skooma/keywords/meta_data/default.rb +11 -0
  82. data/lib/json_skooma/keywords/meta_data/deprecated.rb +11 -0
  83. data/lib/json_skooma/keywords/meta_data/description.rb +11 -0
  84. data/lib/json_skooma/keywords/meta_data/examples.rb +11 -0
  85. data/lib/json_skooma/keywords/meta_data/read_only.rb +11 -0
  86. data/lib/json_skooma/keywords/meta_data/title.rb +11 -0
  87. data/lib/json_skooma/keywords/meta_data/write_only.rb +11 -0
  88. data/lib/json_skooma/keywords/unevaluated/unevaluated_items.rb +59 -0
  89. data/lib/json_skooma/keywords/unevaluated/unevaluated_properties.rb +43 -0
  90. data/lib/json_skooma/keywords/unknown.rb +21 -0
  91. data/lib/json_skooma/keywords/validation/const.rb +17 -0
  92. data/lib/json_skooma/keywords/validation/dependent_required.rb +24 -0
  93. data/lib/json_skooma/keywords/validation/enum.rb +19 -0
  94. data/lib/json_skooma/keywords/validation/exclusive_maximum.rb +18 -0
  95. data/lib/json_skooma/keywords/validation/exclusive_minimum.rb +18 -0
  96. data/lib/json_skooma/keywords/validation/max_contains.rb +24 -0
  97. data/lib/json_skooma/keywords/validation/max_items.rb +18 -0
  98. data/lib/json_skooma/keywords/validation/max_length.rb +18 -0
  99. data/lib/json_skooma/keywords/validation/max_properties.rb +18 -0
  100. data/lib/json_skooma/keywords/validation/maximum.rb +18 -0
  101. data/lib/json_skooma/keywords/validation/min_contains.rb +31 -0
  102. data/lib/json_skooma/keywords/validation/min_items.rb +18 -0
  103. data/lib/json_skooma/keywords/validation/min_length.rb +18 -0
  104. data/lib/json_skooma/keywords/validation/min_properties.rb +18 -0
  105. data/lib/json_skooma/keywords/validation/minimum.rb +18 -0
  106. data/lib/json_skooma/keywords/validation/multiple_of.rb +20 -0
  107. data/lib/json_skooma/keywords/validation/pattern.rb +23 -0
  108. data/lib/json_skooma/keywords/validation/required.rb +19 -0
  109. data/lib/json_skooma/keywords/validation/type.rb +26 -0
  110. data/lib/json_skooma/keywords/validation/unique_items.rb +20 -0
  111. data/lib/json_skooma/keywords/value_schemas.rb +87 -0
  112. data/lib/json_skooma/memoizable.rb +21 -0
  113. data/lib/json_skooma/metaschema.rb +32 -0
  114. data/lib/json_skooma/registry.rb +130 -0
  115. data/lib/json_skooma/result.rb +125 -0
  116. data/lib/json_skooma/sources.rb +55 -0
  117. data/lib/json_skooma/validators/base.rb +31 -0
  118. data/lib/json_skooma/validators/date.rb +18 -0
  119. data/lib/json_skooma/validators/date_time.rb +24 -0
  120. data/lib/json_skooma/validators/duration.rb +25 -0
  121. data/lib/json_skooma/validators/email.rb +36 -0
  122. data/lib/json_skooma/validators/hostname.rb +17 -0
  123. data/lib/json_skooma/validators/idn_email.rb +30 -0
  124. data/lib/json_skooma/validators/idn_hostname.rb +15 -0
  125. data/lib/json_skooma/validators/ipv4.rb +20 -0
  126. data/lib/json_skooma/validators/ipv6.rb +16 -0
  127. data/lib/json_skooma/validators/iri.rb +47 -0
  128. data/lib/json_skooma/validators/iri_reference.rb +15 -0
  129. data/lib/json_skooma/validators/json_pointer.rb +19 -0
  130. data/lib/json_skooma/validators/regex.rb +15 -0
  131. data/lib/json_skooma/validators/relative_json_pointer.rb +18 -0
  132. data/lib/json_skooma/validators/time.rb +32 -0
  133. data/lib/json_skooma/validators/uri.rb +60 -0
  134. data/lib/json_skooma/validators/uri_reference.rb +15 -0
  135. data/lib/json_skooma/validators/uri_template.rb +26 -0
  136. data/lib/json_skooma/validators/uuid.rb +15 -0
  137. data/lib/json_skooma/validators.rb +17 -0
  138. data/lib/json_skooma/version.rb +5 -0
  139. data/lib/json_skooma/vocabulary.rb +12 -0
  140. data/lib/json_skooma.rb +39 -0
  141. metadata +244 -0
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri/idna"
4
+
5
+ module JSONSkooma
6
+ module Validators
7
+ class IdnHostname < Base
8
+ def call(data)
9
+ URI::IDNA.register(ulabel: data.value)
10
+ rescue URI::IDNA::Error => e
11
+ raise FormatError, "#{data} is not a valid IDN hostname: #{e.message}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ipaddr"
4
+
5
+ module JSONSkooma
6
+ module Validators
7
+ class Ipv4 < Base
8
+ self.class
9
+
10
+ class << self
11
+ def call(data)
12
+ ip = IPAddr.new "#{data.value}/24"
13
+ raise FormatError, "must be a valid IPv4 address" unless ip.ipv4?
14
+ rescue IPAddr::Error => e
15
+ raise FormatError, e.message
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ipaddr"
4
+
5
+ module JSONSkooma
6
+ module Validators
7
+ class Ipv6 < Base
8
+ def call(data)
9
+ ip = IPAddr.new "#{data.value}/64"
10
+ raise FormatError, "must be a valid IPv6 address" unless ip.ipv6? && ip.zone_id.nil?
11
+ rescue IPAddr::Error => e
12
+ raise FormatError, e.message
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class Iri < Base
6
+ UCSCHAR = /[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF\u{10000}-\u{1FFFD}]/.freeze
7
+ IPRIVATE = /[\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{10000}-\u{1FFFD}\u{20000}-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}\u{50000}-\u{5FFFD}\u{60000}-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}\u{90000}-\u{9FFFD}\u{A0000}-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}\u{D0000}-\u{DFFFD}\u{E1000}-\u{EFFFD}]/.freeze
8
+ IUNRESERVED = /#{Uri::UNRESERVED}|#{UCSCHAR}/.freeze
9
+
10
+ IPCHAR = /#{IUNRESERVED}|#{Uri::PCT_ENCODED}|#{Uri::SUB_DELIMS}|[:@]/.freeze
11
+
12
+ IQUERY = /(?:#{IPCHAR}|#{IPRIVATE}|[?\/])*/.freeze
13
+ IFRAGMENT = /(?:#{IPCHAR}|[?\/])*/.freeze
14
+
15
+ ISEGMENT = /#{IPCHAR}*/.freeze
16
+ ISEGMENT_NZ = /#{IPCHAR}+/.freeze
17
+ ISEGMENT_NZ_NC = /(?:#{IUNRESERVED}|#{Uri::PCT_ENCODED}|#{Uri::SUB_DELIMS}|@)+/.freeze
18
+
19
+ IPATH_ABEMPTY = /(?:\/#{ISEGMENT})*/.freeze
20
+ IPATH_ABSOLUTE = /\/(?:#{ISEGMENT_NZ}(?:\/#{ISEGMENT})*)?/.freeze
21
+ IPATH_NOSCHEME = /#{ISEGMENT_NZ_NC}(?:\/#{ISEGMENT})*/.freeze
22
+ IPATH_ROOTLESS = /#{ISEGMENT_NZ}(?:\/#{ISEGMENT})*/.freeze
23
+ IPATH_OLD = /#{IPATH_ABEMPTY}|#{IPATH_ABSOLUTE}|#{IPATH_NOSCHEME}|#{IPATH_ROOTLESS}|/.freeze
24
+
25
+ IREG_NAME = /(?:#{IUNRESERVED}|#{Uri::PCT_ENCODED}|#{Uri::SUB_DELIMS})*/.freeze
26
+ IHOST = /#{Uri::IP_LITERAL}|#{Uri::IPV4_ADDRESS}|#{IREG_NAME}/.freeze
27
+ IUSERINFO = /(?:#{IUNRESERVED}|#{Uri::PCT_ENCODED}|#{Uri::SUB_DELIMS}|:)*/.freeze
28
+ IAUTHORITY = /(?:#{IUSERINFO}@)?#{IHOST}(?::#{Uri::PORT})?/.freeze
29
+
30
+ IHIER_PART = /(?:\/\/#{IAUTHORITY}#{IPATH_ABEMPTY})|#{IPATH_ABSOLUTE}|#{IPATH_ROOTLESS}|/.freeze
31
+
32
+ IRI = /#{Uri::SCHEME}:#{IHIER_PART}(?:\?#{IQUERY})?(?:##{IFRAGMENT})?/.freeze
33
+
34
+ IRELATIVE_PATH = /(?:\/\/#{IAUTHORITY}#{IPATH_ABEMPTY})|#{IPATH_ABSOLUTE}|#{IPATH_NOSCHEME}|/
35
+ IRELATIVE_REF = /#{IRELATIVE_PATH}(?:\?#{IQUERY})?(?:##{IFRAGMENT})?/.freeze
36
+ IRI_REFERENCE = /#{IRI}|#{IRELATIVE_REF}/.freeze
37
+
38
+ REGEX = /\A#{IRI}\z/.freeze
39
+
40
+ def call(data)
41
+ return if REGEX.match?(data.value)
42
+
43
+ raise FormatError, "#{data} is not a valid IRI"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class IriReference < Base
6
+ REGEX = /\A#{Iri::IRI_REFERENCE}\z/.freeze
7
+
8
+ def call(data)
9
+ return if REGEX.match?(data.value)
10
+
11
+ raise FormatError, "#{data} is not a valid IRI reference"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class JSONPointer < Base
6
+ ESC = /~[01]/
7
+ UNESC = /[\u0000-\u002E\u0030-\u007d\u007F-\u{10FFFF}]/
8
+ TOKEN = /(#{ESC}|#{UNESC})*/
9
+ JSON_POINTER = /(\/#{TOKEN})*/
10
+ REGEXP = /\A#{JSON_POINTER}\z/
11
+
12
+ def call(data)
13
+ return if REGEXP.match?(data)
14
+
15
+ raise FormatError, "#{data} is not a valid JSON pointer"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "regexp_parser"
4
+
5
+ module JSONSkooma
6
+ module Validators
7
+ class Regex < Base
8
+ def call(data)
9
+ Regexp::Parser.parse(data)
10
+ rescue Regexp::Scanner::ScannerError => e
11
+ raise FormatError, e.message
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class RelativeJSONPointer < Base
6
+ NN_INT = /0|[1-9][0-9]*/
7
+ INDEX = /[+-]#{NN_INT}/
8
+ RELATIVE_JSON_POINTER = /(#{NN_INT}(#{INDEX})?#{JSONPointer::JSON_POINTER})|(#{NN_INT}#)/
9
+ REGEXP = /\A#{RELATIVE_JSON_POINTER}\z/
10
+
11
+ def call(data)
12
+ return if REGEXP.match?(data)
13
+
14
+ raise FormatError, "#{data} is not a valid JSON pointer"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class Time < Base
6
+ REGEXP = /\A#{DateTime::FULL_TIME}\z/
7
+
8
+ def call(data)
9
+ match = REGEXP.match(data)
10
+
11
+ if match.nil? || !valid_leap_seconds?(match)
12
+ raise FormatError, "must be a valid RFC 3339 time string"
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def valid_leap_seconds?(match)
19
+ return true if match[:s].to_i != 60
20
+
21
+ time = match[:h].to_i * 60 + match[:m].to_i
22
+ if match[:on]
23
+ sign = (match[:on] == "+") ? -1 : 1
24
+ time += sign * (match[:oh].to_i * 60 + match[:om].to_i)
25
+ time = time % (60 * 24)
26
+ end
27
+ leap_time = 23 * 60 + 59
28
+ time == leap_time
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class Uri < Base
6
+ SUB_DELIMS = /[!$&'()*+,;=]/.freeze
7
+ GEN_DELIMS = /[:\/?#\[\]@]/.freeze
8
+ RESERVED = /(?:#{GEN_DELIMS}|#{SUB_DELIMS})/.freeze
9
+ UNRESERVED = /[A-Za-z\d\-._~]/.freeze
10
+ PCT_ENCODED = /%\h{2}/.freeze
11
+ PCHAR = /(?:#{UNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|[:@])/.freeze
12
+ FRAGMENT = /(?:#{PCHAR}|[?\/])*/.freeze
13
+ QUERY = FRAGMENT
14
+
15
+ SEGMENT = /#{PCHAR}*/.freeze
16
+ SEGMENT_NZ = /#{PCHAR}+/.freeze
17
+ SEGMENT_NZ_NC = /(?:#{UNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|@)+/.freeze
18
+
19
+ PATH_ABEMPTY = /(?:\/#{SEGMENT})*/.freeze
20
+ PATH_ABSOLUTE = /\/(?:#{SEGMENT_NZ}(?:\/#{SEGMENT})*)?/.freeze
21
+ PATH_NOSCHEME = /#{SEGMENT_NZ_NC}(?:\/#{SEGMENT})*/.freeze
22
+ PATH_ROOTLESS = /#{SEGMENT_NZ}(?:\/#{SEGMENT})*/.freeze
23
+ PATH = /(?:#{PATH_ABEMPTY}|#{PATH_ABSOLUTE}|#{PATH_NOSCHEME}|#{PATH_ROOTLESS})?/.freeze
24
+
25
+ IPV4_ADDRESS = /((25[0-5]|(2[0-4]|1\d|[1-9])?\d)\.?\b){4}/
26
+ H16 = /\h{1,4}/
27
+ LS32 = /(?:#{H16}:#{H16})|#{IPV4_ADDRESS}/
28
+ IPV6_ADDRESS = /(?:#{H16}:){6}#{LS32}|::(?:#{H16}:){5}#{LS32}|(?:#{H16})?::(?:#{H16}:){4}#{LS32}|(?:(?:#{H16}:){0,1}#{H16})?::(?:#{H16}:){3}#{LS32}|(?:(?:#{H16}:){0,2}#{H16})?::(?:#{H16}:){2}#{LS32}|(?:(?:#{H16}:){0,3}#{H16})?::(?:#{H16}:){1}#{LS32}|(?:(?:#{H16}:){0,4}#{H16})?::#{LS32}|(?:(?:#{H16}:){0,5}#{H16})?::#{H16}|(?:(?:#{H16}:){0,6}#{H16})?::/.freeze
29
+
30
+ IPV_FUTURE = /v\h+\.(?:#{UNRESERVED}|#{SUB_DELIMS}|:)+/.freeze
31
+ IP_LITERAL = /\[(?:#{IPV6_ADDRESS}|#{IPV_FUTURE})\]/.freeze
32
+
33
+ PORT = /\d*/.freeze
34
+ REG_NAME = /(?:#{UNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS})*/.freeze
35
+ HOST = /(?:#{IP_LITERAL}|#{IPV4_ADDRESS}|#{REG_NAME})/.freeze
36
+ USERINFO = /(?:#{UNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|:)*/.freeze
37
+ AUTHORITY = /(?:#{USERINFO}@)?#{HOST}(?::#{PORT})?/.freeze
38
+
39
+ SCHEME = /[a-zA-Z][a-zA-Z\d+.-]*/.freeze
40
+
41
+ HIER_PART = /(?:(?:\/\/#{AUTHORITY}#{PATH_ABEMPTY})|#{PATH_ABSOLUTE}|#{PATH_ROOTLESS})?/.freeze
42
+
43
+ URI = /#{SCHEME}:#{HIER_PART}(?:\?#{QUERY})?(?:##{FRAGMENT})?/.freeze
44
+
45
+ # ABSOLUTE_URI = /#{SCHEME}:#{HIER_PART}(?:\?#{QUERY})?/.freeze
46
+
47
+ RELATIVE_PART = /(?:(?:\/\/#{AUTHORITY}#{PATH_ABEMPTY})|#{PATH_ABSOLUTE}|#{PATH_NOSCHEME})?/.freeze
48
+ RELATIVE_REF = /#{RELATIVE_PART}(?:\?#{QUERY})?(?:##{FRAGMENT})?/.freeze
49
+ URI_REFERENCE = /#{URI}|#{RELATIVE_REF}/.freeze
50
+
51
+ REGEX = /\A#{URI}\z/.freeze
52
+
53
+ def call(data)
54
+ return if REGEX.match?(data.value)
55
+
56
+ raise FormatError, "#{data} is not a valid URI"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class UriReference < Base
6
+ REGEX = /\A#{Uri::URI_REFERENCE}\z/.freeze
7
+
8
+ def call(data)
9
+ return if REGEX.match?(data.value)
10
+
11
+ raise FormatError, "#{data} is not a valid URI reference"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class UriTemplate < Base
6
+ PCT = /%\h\h/
7
+ VAR_CHAR = /[A-Za-z\d_]|(#{PCT})/
8
+ VAR_NAME = /#{VAR_CHAR}(\.?#{VAR_CHAR})*/
9
+ MOD4 = /(:[1-9]\d{0,3}|(\*)?)/
10
+ VAR_SPEC = /#{VAR_NAME}(#{MOD4})?/
11
+ VAR_LIST = /#{VAR_SPEC}(,#{VAR_SPEC})*/
12
+ OPERATOR = /[+#.\/;?&=,!@|]/
13
+ EXPRESSION = /\{#{OPERATOR}?#{VAR_LIST}\}/
14
+ LITERALS = /[^\x00-\x20\x7F"'%<>\\^`{|}]/
15
+ URI_TEMPLATE = /((#{LITERALS})|(#{EXPRESSION}))*/
16
+
17
+ REGEXP = /\A#{URI_TEMPLATE}\z/
18
+
19
+ def call(data)
20
+ return if REGEXP.match?(data)
21
+
22
+ raise FormatError, "#{data} is not a valid URI template"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class Uuid < Base
6
+ REGEXP = /\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/
7
+
8
+ def call(data)
9
+ return if REGEXP.match?(data)
10
+
11
+ raise FormatError, "#{data} is not a valid UUID"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ module Validators
5
+ class FormatError < StandardError; end
6
+
7
+ class << self
8
+ attr_accessor :validators
9
+
10
+ def register(name, validator)
11
+ validators[name] = validator
12
+ end
13
+ end
14
+
15
+ self.validators = {}
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONSkooma
4
+ class Vocabulary
5
+ attr_reader :kw_classes, :uri
6
+
7
+ def initialize(uri, *keywords)
8
+ @kw_classes = keywords.map { |keyword| [keyword.key, keyword] }.to_h
9
+ @uri = uri
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "zeitwerk"
5
+
6
+ require_relative "json_skooma/inflector"
7
+
8
+ loader = Zeitwerk::Loader.for_gem
9
+ loader.inflector = JSONSkooma::Inflector.new
10
+ loader.setup
11
+
12
+ module JSONSkooma
13
+ DATA_DIR = File.join(__dir__, "..", "data")
14
+
15
+ class Error < StandardError; end
16
+
17
+ class << self
18
+ attr_accessor :dialects
19
+
20
+ def register_dialect(version_key, dialect)
21
+ dialects[version_key] = dialect
22
+ end
23
+
24
+ def create_registry(*schema_dialects, name: Registry::DEFAULT_NAME, assert_formats: false)
25
+ registry = Registry.new(name: name)
26
+
27
+ schema_dialects.each do |version_key|
28
+ dialects.fetch(version_key).call(registry, assert_formats: assert_formats)
29
+ end
30
+
31
+ registry
32
+ end
33
+ end
34
+
35
+ self.dialects = {}
36
+
37
+ register_dialect("2019-09", Dialects::Draft201909)
38
+ register_dialect("2020-12", Dialects::Draft202012)
39
+ end
metadata ADDED
@@ -0,0 +1,244 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json_skooma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Svyatoslav Kryukov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: zeitwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hana
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: regexp_parser
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: uri-idna
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
69
+ description: I bring some sugar for your JSONs.
70
+ email:
71
+ - s.g.kryukov@yandex.ru
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - CHANGELOG.md
77
+ - LICENSE.txt
78
+ - README.md
79
+ - data/draft-2019-09/README.md
80
+ - data/draft-2019-09/hyper-schema.json
81
+ - data/draft-2019-09/links.json
82
+ - data/draft-2019-09/meta/applicator.json
83
+ - data/draft-2019-09/meta/content.json
84
+ - data/draft-2019-09/meta/core.json
85
+ - data/draft-2019-09/meta/format.json
86
+ - data/draft-2019-09/meta/hyper-schema.json
87
+ - data/draft-2019-09/meta/meta-data.json
88
+ - data/draft-2019-09/meta/validation.json
89
+ - data/draft-2019-09/output/hyper-schema.json
90
+ - data/draft-2019-09/output/schema.json
91
+ - data/draft-2019-09/output/verbose-example.json
92
+ - data/draft-2019-09/schema.json
93
+ - data/draft-2020-12/README.md
94
+ - data/draft-2020-12/adr/README.md
95
+ - data/draft-2020-12/archive/hyper-schema.json
96
+ - data/draft-2020-12/archive/links.json
97
+ - data/draft-2020-12/archive/meta/hyper-schema.json
98
+ - data/draft-2020-12/hyper-schema.json
99
+ - data/draft-2020-12/links.json
100
+ - data/draft-2020-12/meta/applicator.json
101
+ - data/draft-2020-12/meta/content.json
102
+ - data/draft-2020-12/meta/core.json
103
+ - data/draft-2020-12/meta/format-annotation.json
104
+ - data/draft-2020-12/meta/format-assertion.json
105
+ - data/draft-2020-12/meta/hyper-schema.json
106
+ - data/draft-2020-12/meta/meta-data.json
107
+ - data/draft-2020-12/meta/unevaluated.json
108
+ - data/draft-2020-12/meta/validation.json
109
+ - data/draft-2020-12/output/hyper-schema.json
110
+ - data/draft-2020-12/output/schema.json
111
+ - data/draft-2020-12/output/verbose-example.json
112
+ - data/draft-2020-12/schema.json
113
+ - lib/json_skooma.rb
114
+ - lib/json_skooma/dialects/draft201909.rb
115
+ - lib/json_skooma/dialects/draft202012.rb
116
+ - lib/json_skooma/formatters.rb
117
+ - lib/json_skooma/inflector.rb
118
+ - lib/json_skooma/json_node.rb
119
+ - lib/json_skooma/json_pointer.rb
120
+ - lib/json_skooma/json_schema.rb
121
+ - lib/json_skooma/keywords/applicator/additional_properties.rb
122
+ - lib/json_skooma/keywords/applicator/all_of.rb
123
+ - lib/json_skooma/keywords/applicator/any_of.rb
124
+ - lib/json_skooma/keywords/applicator/contains.rb
125
+ - lib/json_skooma/keywords/applicator/dependent_schemas.rb
126
+ - lib/json_skooma/keywords/applicator/else.rb
127
+ - lib/json_skooma/keywords/applicator/if.rb
128
+ - lib/json_skooma/keywords/applicator/items.rb
129
+ - lib/json_skooma/keywords/applicator/not.rb
130
+ - lib/json_skooma/keywords/applicator/one_of.rb
131
+ - lib/json_skooma/keywords/applicator/pattern_properties.rb
132
+ - lib/json_skooma/keywords/applicator/prefix_items.rb
133
+ - lib/json_skooma/keywords/applicator/properties.rb
134
+ - lib/json_skooma/keywords/applicator/property_names.rb
135
+ - lib/json_skooma/keywords/applicator/then.rb
136
+ - lib/json_skooma/keywords/base.rb
137
+ - lib/json_skooma/keywords/base_annotation.rb
138
+ - lib/json_skooma/keywords/content/content_encoding.rb
139
+ - lib/json_skooma/keywords/content/content_media_type.rb
140
+ - lib/json_skooma/keywords/content/content_schema.rb
141
+ - lib/json_skooma/keywords/core/anchor.rb
142
+ - lib/json_skooma/keywords/core/comment.rb
143
+ - lib/json_skooma/keywords/core/defs.rb
144
+ - lib/json_skooma/keywords/core/dynamic_anchor.rb
145
+ - lib/json_skooma/keywords/core/dynamic_ref.rb
146
+ - lib/json_skooma/keywords/core/id.rb
147
+ - lib/json_skooma/keywords/core/ref.rb
148
+ - lib/json_skooma/keywords/core/schema.rb
149
+ - lib/json_skooma/keywords/core/vocabulary.rb
150
+ - lib/json_skooma/keywords/draft_2019_09/additional_items.rb
151
+ - lib/json_skooma/keywords/draft_2019_09/items.rb
152
+ - lib/json_skooma/keywords/draft_2019_09/recursive_anchor.rb
153
+ - lib/json_skooma/keywords/draft_2019_09/recursive_ref.rb
154
+ - lib/json_skooma/keywords/draft_2019_09/unevaluated_items.rb
155
+ - lib/json_skooma/keywords/format_annotation/format.rb
156
+ - lib/json_skooma/keywords/meta_data/default.rb
157
+ - lib/json_skooma/keywords/meta_data/deprecated.rb
158
+ - lib/json_skooma/keywords/meta_data/description.rb
159
+ - lib/json_skooma/keywords/meta_data/examples.rb
160
+ - lib/json_skooma/keywords/meta_data/read_only.rb
161
+ - lib/json_skooma/keywords/meta_data/title.rb
162
+ - lib/json_skooma/keywords/meta_data/write_only.rb
163
+ - lib/json_skooma/keywords/unevaluated/unevaluated_items.rb
164
+ - lib/json_skooma/keywords/unevaluated/unevaluated_properties.rb
165
+ - lib/json_skooma/keywords/unknown.rb
166
+ - lib/json_skooma/keywords/validation/const.rb
167
+ - lib/json_skooma/keywords/validation/dependent_required.rb
168
+ - lib/json_skooma/keywords/validation/enum.rb
169
+ - lib/json_skooma/keywords/validation/exclusive_maximum.rb
170
+ - lib/json_skooma/keywords/validation/exclusive_minimum.rb
171
+ - lib/json_skooma/keywords/validation/max_contains.rb
172
+ - lib/json_skooma/keywords/validation/max_items.rb
173
+ - lib/json_skooma/keywords/validation/max_length.rb
174
+ - lib/json_skooma/keywords/validation/max_properties.rb
175
+ - lib/json_skooma/keywords/validation/maximum.rb
176
+ - lib/json_skooma/keywords/validation/min_contains.rb
177
+ - lib/json_skooma/keywords/validation/min_items.rb
178
+ - lib/json_skooma/keywords/validation/min_length.rb
179
+ - lib/json_skooma/keywords/validation/min_properties.rb
180
+ - lib/json_skooma/keywords/validation/minimum.rb
181
+ - lib/json_skooma/keywords/validation/multiple_of.rb
182
+ - lib/json_skooma/keywords/validation/pattern.rb
183
+ - lib/json_skooma/keywords/validation/required.rb
184
+ - lib/json_skooma/keywords/validation/type.rb
185
+ - lib/json_skooma/keywords/validation/unique_items.rb
186
+ - lib/json_skooma/keywords/value_schemas.rb
187
+ - lib/json_skooma/memoizable.rb
188
+ - lib/json_skooma/metaschema.rb
189
+ - lib/json_skooma/registry.rb
190
+ - lib/json_skooma/result.rb
191
+ - lib/json_skooma/sources.rb
192
+ - lib/json_skooma/validators.rb
193
+ - lib/json_skooma/validators/base.rb
194
+ - lib/json_skooma/validators/date.rb
195
+ - lib/json_skooma/validators/date_time.rb
196
+ - lib/json_skooma/validators/duration.rb
197
+ - lib/json_skooma/validators/email.rb
198
+ - lib/json_skooma/validators/hostname.rb
199
+ - lib/json_skooma/validators/idn_email.rb
200
+ - lib/json_skooma/validators/idn_hostname.rb
201
+ - lib/json_skooma/validators/ipv4.rb
202
+ - lib/json_skooma/validators/ipv6.rb
203
+ - lib/json_skooma/validators/iri.rb
204
+ - lib/json_skooma/validators/iri_reference.rb
205
+ - lib/json_skooma/validators/json_pointer.rb
206
+ - lib/json_skooma/validators/regex.rb
207
+ - lib/json_skooma/validators/relative_json_pointer.rb
208
+ - lib/json_skooma/validators/time.rb
209
+ - lib/json_skooma/validators/uri.rb
210
+ - lib/json_skooma/validators/uri_reference.rb
211
+ - lib/json_skooma/validators/uri_template.rb
212
+ - lib/json_skooma/validators/uuid.rb
213
+ - lib/json_skooma/version.rb
214
+ - lib/json_skooma/vocabulary.rb
215
+ homepage: https://github.com/skryukov/json_skooma
216
+ licenses:
217
+ - MIT
218
+ metadata:
219
+ bug_tracker_uri: https://github.com/skryukov/json_skooma/issues
220
+ changelog_uri: https://github.com/skryukov/json_skooma/blob/main/CHANGELOG.md
221
+ documentation_uri: https://github.com/skryukov/json_skooma/blob/main/README.md
222
+ homepage_uri: https://github.com/skryukov/json_skooma
223
+ source_code_uri: https://github.com/skryukov/json_skooma
224
+ rubygems_mfa_required: 'true'
225
+ post_install_message:
226
+ rdoc_options: []
227
+ require_paths:
228
+ - lib
229
+ required_ruby_version: !ruby/object:Gem::Requirement
230
+ requirements:
231
+ - - ">="
232
+ - !ruby/object:Gem::Version
233
+ version: 2.6.0
234
+ required_rubygems_version: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - ">="
237
+ - !ruby/object:Gem::Version
238
+ version: '0'
239
+ requirements: []
240
+ rubygems_version: 3.3.7
241
+ signing_key:
242
+ specification_version: 4
243
+ summary: I bring some sugar for your JSONs.
244
+ test_files: []