json_skooma 0.1.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.
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: []