schemacop 3.0.37 → 3.0.38

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56a24074bd3792c20ee7e2f0bb1a8c3f4aa6d411a9a4c8010c9a52f0e828e6a3
4
- data.tar.gz: ca4a752be493fe721122a77c5fb6844098c968dddf860fdcb0e33ef9a98880c3
3
+ metadata.gz: 4a3a54c489ac60b4a01424d7a4949724c15fdec793de16a4375e3097f691128b
4
+ data.tar.gz: 48390b41d456f5362ecabf0e97ed37fdc035247ec3d8335d105e97ab0d858378
5
5
  SHA512:
6
- metadata.gz: da3e3672206befe40e6487677c6c879192a3fdaf450e3621566be86dd1ccc9c487571a70cf7f1933294d5de9cd86094791e22cd659109a97baa432917138f296
7
- data.tar.gz: 69d79cf5ad0702b80f930a9227f9279c2f758b3cb51965596145d82ec735b0fe8bb6648f219b6c1858d82f8a339ccdc388db71c3767573a074562a063eefcade
6
+ metadata.gz: 911a618277694321833a85cc051ff139b14e9a1117dab7380bcc4c9ebc08e87a258f131224e1f3cef40d5b6495de6142f1b6f23009ce62917c8a07bf75960678
7
+ data.tar.gz: 1add721c851198435cf89b0b9d95d94c607bc443df180072fda1b35d4b956a4a2bdab429252f630fca8e4ddf09baf13153278d60f401318e0ad591bbc7c481b8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Change log
2
2
 
3
+ ## 3.0.38 (2026-02-25)
4
+
5
+ * Fix namespaced schema `$ref` paths in generated JSON. For OpenAPI (swagger)
6
+ output, `/` and `~` in schema paths are replaced with `.` (e.g.
7
+ `namespaced/user` becomes `namespaced.user`) to comply with the OpenAPI schema
8
+ name format. For plain JSON Schema output, paths are escaped per RFC 6901
9
+ (`~0` for `~`, `~1` for `/`).
10
+
11
+ Internal reference: `#146922`.
12
+
13
+ * Fix `CombinationNode` (`one_of`, `any_of`, `all_of`) not exposing its items
14
+ via `children`. This caused `used_external_schemas` to miss any `ref` nodes
15
+ nested inside combination nodes, leading to missing entries in
16
+ `components.schemas` in OpenAPI output.
17
+
18
+ * Normalize `ReferenceNode` path to symbol. When a schema reference is created
19
+ with a string path (e.g. `ref 'foo'`), the path is now converted to a symbol
20
+ to match the keys used by `GlobalContext`.
21
+
22
+ Internal reference: `#146922`.
23
+
3
24
  ## 3.0.37 (2026-02-24)
4
25
 
5
26
  * Add inline ref support for hash nodes via `ref! nil, :SchemaName`. This
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.37
1
+ 3.0.38
@@ -23,6 +23,10 @@ module Schemacop
23
23
  return item.cast(value)
24
24
  end
25
25
 
26
+ def children
27
+ @items
28
+ end
29
+
26
30
  def add_child(node)
27
31
  @items << node
28
32
  end
@@ -1,6 +1,8 @@
1
1
  module Schemacop
2
2
  module V3
3
3
  class ReferenceNode < Node
4
+ RFC6901_ESCAPE = { '~' => '~0', '/' => '~1' }.freeze
5
+
4
6
  def self.allowed_options
5
7
  super + %i[path]
6
8
  end
@@ -12,9 +14,16 @@ module Schemacop
12
14
 
13
15
  def as_json
14
16
  if context.swagger_json?
15
- process_json([], '$ref': "#/components/schemas/#{@path}")
17
+ # OpenAPI schema names must match ^[a-zA-Z0-9._-]+$, so we replace
18
+ # all non-conforming characters: `/` and `~` become `.`.
19
+ sanitized = @path.to_s.gsub(%r{[~/]}, '.')
20
+ process_json([], '$ref': "#/components/schemas/#{sanitized}")
16
21
  else
17
- process_json([], '$ref': "#/definitions/#{@path}")
22
+ # Plain JSON Schema: use RFC 6901 JSON Pointer escaping in $ref.
23
+ # gsub with a hash is a single-pass substitution, so the RFC 6901
24
+ # order-of-escaping concern (~ before /) does not apply here.
25
+ escaped = @path.to_s.gsub(%r{[~/]}, RFC6901_ESCAPE)
26
+ process_json([], '$ref': "#/definitions/#{escaped}")
18
27
  end
19
28
  end
20
29
 
@@ -56,7 +65,7 @@ module Schemacop
56
65
  protected
57
66
 
58
67
  def init
59
- @path = options.delete(:path)
68
+ @path = options.delete(:path)&.to_sym
60
69
  end
61
70
  end
62
71
  end
data/schemacop.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: schemacop 3.0.37 ruby lib
2
+ # stub: schemacop 3.0.38 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "schemacop".freeze
6
- s.version = "3.0.37".freeze
6
+ s.version = "3.0.38".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Sitrox".freeze]
11
- s.date = "2026-02-24"
11
+ s.date = "2026-02-25"
12
12
  s.files = [".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".yardopts".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "README_V2.md".freeze, "README_V3.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "lib/schemacop.rb".freeze, "lib/schemacop/base_schema.rb".freeze, "lib/schemacop/exceptions.rb".freeze, "lib/schemacop/railtie.rb".freeze, "lib/schemacop/schema.rb".freeze, "lib/schemacop/schema2.rb".freeze, "lib/schemacop/schema3.rb".freeze, "lib/schemacop/scoped_env.rb".freeze, "lib/schemacop/v2.rb".freeze, "lib/schemacop/v2/caster.rb".freeze, "lib/schemacop/v2/collector.rb".freeze, "lib/schemacop/v2/dupper.rb".freeze, "lib/schemacop/v2/field_node.rb".freeze, "lib/schemacop/v2/node.rb".freeze, "lib/schemacop/v2/node_resolver.rb".freeze, "lib/schemacop/v2/node_supporting_field.rb".freeze, "lib/schemacop/v2/node_supporting_type.rb".freeze, "lib/schemacop/v2/node_with_block.rb".freeze, "lib/schemacop/v2/validator/array_validator.rb".freeze, "lib/schemacop/v2/validator/boolean_validator.rb".freeze, "lib/schemacop/v2/validator/float_validator.rb".freeze, "lib/schemacop/v2/validator/hash_validator.rb".freeze, "lib/schemacop/v2/validator/integer_validator.rb".freeze, "lib/schemacop/v2/validator/nil_validator.rb".freeze, "lib/schemacop/v2/validator/number_validator.rb".freeze, "lib/schemacop/v2/validator/object_validator.rb".freeze, "lib/schemacop/v2/validator/string_validator.rb".freeze, "lib/schemacop/v2/validator/symbol_validator.rb".freeze, "lib/schemacop/v3.rb".freeze, "lib/schemacop/v3/all_of_node.rb".freeze, "lib/schemacop/v3/any_of_node.rb".freeze, "lib/schemacop/v3/array_node.rb".freeze, "lib/schemacop/v3/boolean_node.rb".freeze, "lib/schemacop/v3/combination_node.rb".freeze, "lib/schemacop/v3/context.rb".freeze, "lib/schemacop/v3/dsl_scope.rb".freeze, "lib/schemacop/v3/global_context.rb".freeze, "lib/schemacop/v3/hash_node.rb".freeze, "lib/schemacop/v3/integer_node.rb".freeze, "lib/schemacop/v3/is_not_node.rb".freeze, "lib/schemacop/v3/node.rb".freeze, "lib/schemacop/v3/node_registry.rb".freeze, "lib/schemacop/v3/number_node.rb".freeze, "lib/schemacop/v3/numeric_node.rb".freeze, "lib/schemacop/v3/object_node.rb".freeze, "lib/schemacop/v3/one_of_node.rb".freeze, "lib/schemacop/v3/reference_node.rb".freeze, "lib/schemacop/v3/result.rb".freeze, "lib/schemacop/v3/string_node.rb".freeze, "lib/schemacop/v3/symbol_node.rb".freeze, "schemacop.gemspec".freeze, "test/lib/test_helper.rb".freeze, "test/schemas/nested/group.rb".freeze, "test/schemas/user.rb".freeze, "test/unit/schemacop/v2/casting_test.rb".freeze, "test/unit/schemacop/v2/collector_test.rb".freeze, "test/unit/schemacop/v2/custom_check_test.rb".freeze, "test/unit/schemacop/v2/custom_if_test.rb".freeze, "test/unit/schemacop/v2/defaults_test.rb".freeze, "test/unit/schemacop/v2/empty_test.rb".freeze, "test/unit/schemacop/v2/nil_dis_allow_test.rb".freeze, "test/unit/schemacop/v2/node_resolver_test.rb".freeze, "test/unit/schemacop/v2/short_forms_test.rb".freeze, "test/unit/schemacop/v2/types_test.rb".freeze, "test/unit/schemacop/v2/validator_array_test.rb".freeze, "test/unit/schemacop/v2/validator_boolean_test.rb".freeze, "test/unit/schemacop/v2/validator_float_test.rb".freeze, "test/unit/schemacop/v2/validator_hash_test.rb".freeze, "test/unit/schemacop/v2/validator_integer_test.rb".freeze, "test/unit/schemacop/v2/validator_nil_test.rb".freeze, "test/unit/schemacop/v2/validator_number_test.rb".freeze, "test/unit/schemacop/v2/validator_object_test.rb".freeze, "test/unit/schemacop/v2/validator_string_test.rb".freeze, "test/unit/schemacop/v2/validator_symbol_test.rb".freeze, "test/unit/schemacop/v3/all_of_node_test.rb".freeze, "test/unit/schemacop/v3/any_of_node_test.rb".freeze, "test/unit/schemacop/v3/array_node_test.rb".freeze, "test/unit/schemacop/v3/boolean_node_test.rb".freeze, "test/unit/schemacop/v3/global_context_test.rb".freeze, "test/unit/schemacop/v3/hash_node_test.rb".freeze, "test/unit/schemacop/v3/integer_node_test.rb".freeze, "test/unit/schemacop/v3/is_not_node_test.rb".freeze, "test/unit/schemacop/v3/node_test.rb".freeze, "test/unit/schemacop/v3/number_node_test.rb".freeze, "test/unit/schemacop/v3/object_node_test.rb".freeze, "test/unit/schemacop/v3/one_of_node_test.rb".freeze, "test/unit/schemacop/v3/reference_node_test.rb".freeze, "test/unit/schemacop/v3/string_node_test.rb".freeze, "test/unit/schemacop/v3/symbol_node_test.rb".freeze]
13
13
  s.homepage = "https://github.com/sitrox/schemacop".freeze
14
14
  s.licenses = ["MIT".freeze]
@@ -706,6 +706,104 @@ module Schemacop
706
706
  end
707
707
  end
708
708
 
709
+ def test_namespaced_schema_reference
710
+ context = Context.new
711
+
712
+ context.schema :'namespaced/user' do
713
+ str! :name
714
+ end
715
+
716
+ Schemacop.with_context context do
717
+ schema do
718
+ ref! :user, :'namespaced/user'
719
+ end
720
+
721
+ assert_json({
722
+ properties: {
723
+ user: {
724
+ '$ref' => '#/definitions/namespaced~1user'
725
+ }
726
+ },
727
+ additionalProperties: false,
728
+ required: %w[user],
729
+ type: :object
730
+ })
731
+
732
+ assert_swagger_json({
733
+ properties: {
734
+ user: {
735
+ '$ref' => '#/components/schemas/namespaced.user'
736
+ }
737
+ },
738
+ additionalProperties: false,
739
+ required: %w[user],
740
+ type: :object
741
+ })
742
+
743
+ assert_validation(user: { name: 'John' })
744
+ assert_validation(user: { name: 42 }) do
745
+ error '/user/name', 'Invalid type, got type "Integer", expected "string".'
746
+ end
747
+ end
748
+ end
749
+
750
+ def test_namespaced_schema_reference_with_tilde
751
+ context = Context.new
752
+
753
+ context.schema :'config~item/sub' do
754
+ str! :value
755
+ end
756
+
757
+ Schemacop.with_context context do
758
+ schema do
759
+ ref! :item, :'config~item/sub'
760
+ end
761
+
762
+ assert_json({
763
+ properties: {
764
+ item: {
765
+ '$ref' => '#/definitions/config~0item~1sub'
766
+ }
767
+ },
768
+ additionalProperties: false,
769
+ required: %w[item],
770
+ type: :object
771
+ })
772
+
773
+ assert_swagger_json({
774
+ properties: {
775
+ item: {
776
+ '$ref' => '#/components/schemas/config.item.sub'
777
+ }
778
+ },
779
+ additionalProperties: false,
780
+ required: %w[item],
781
+ type: :object
782
+ })
783
+
784
+ assert_validation(item: { value: 'hello' })
785
+ end
786
+ end
787
+
788
+ def test_ref_inside_one_of_used_external_schemas
789
+ context = Context.new
790
+
791
+ context.schema :Nested do
792
+ str! :value
793
+ end
794
+
795
+ Schemacop.with_context context do
796
+ schema do
797
+ one_of! :item do
798
+ ref :Nested
799
+ str
800
+ end
801
+ end
802
+
803
+ assert_includes @schema.root.used_external_schemas, :Nested
804
+ end
805
+ end
806
+
709
807
  def test_inline_ref_property_name_collision
710
808
  schema do
711
809
  scm :BasicInfo do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schemacop
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.37
4
+ version: 3.0.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-02-24 00:00:00.000000000 Z
10
+ date: 2026-02-25 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport