jsonapi-resources-anchor 2.11.1 → 2.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e653189b74aa45f96e4fd6a0e7f50623ddec2482ba913a3b69d6c5a5265541d
4
- data.tar.gz: 2ce59101060a5da7c1ad982012eab85112c4809deda41cea99170dac6bf88a4d
3
+ metadata.gz: 2a315147926ca737e06a0b594d33a8a5d435333abfb529c2ae8fade5342a641e
4
+ data.tar.gz: 13fd9b832e61b49bec167c58b45700b5b527fee09d4eb555f4dc4a4680395078
5
5
  SHA512:
6
- metadata.gz: e9d7c8469c790d7461b9d959b45022648151ed429c082016115f7ea8c7f5229b4d1028bd72d7cd78b12be4ce93b502f246b78147bb65501c2a5bb2be7b84e286
7
- data.tar.gz: 628ff8ae3d24a17d9698de87f6bb0010cb57c5f7d66c487c6a11a7f2fd1554a6800d60c944891668bdc8b20fdbabb894131bb2ae35248f02d650b6a1658733e2
6
+ metadata.gz: 48ad87a68af94a2774d734ac8b591e1e77f25f558706d0b9de4d95d81f136b7edbd5a161c62732d5c5f5e35e94bbf1352dfffc54ab44b2b3b4c7b6dbaf98e4cd
7
+ data.tar.gz: 4d0ed1301e0a22b61c867603b8484d7bcf7a925365caa7c90032981f19dab78e2487e3f239bfdd86bf71c75c9bc7cf9888bc62c8c42f27d6237053c64772af65
@@ -21,6 +21,7 @@ module Anchor::JSONSchema
21
21
  when Anchor::Types::Object, Anchor::Types::Object.singleton_class then serialize_object(type)
22
22
  when Anchor::Types::Enum.singleton_class then { enum: type.values.map(&:second) }
23
23
  when Anchor::Types::Unknown.singleton_class then {}
24
+ when Anchor::Types::Intersection then {}
24
25
  else raise RuntimeError
25
26
  end
26
27
  end
@@ -79,7 +79,13 @@ module Anchor
79
79
  enum = Anchor.config.infer_ar_enums && !method_defined && _model_class.try(:defined_enums).try(:[], model_method.to_s)
80
80
  column = !method_defined && _model_class.try(:columns_hash).try(:[], model_method.to_s)
81
81
 
82
- if column
82
+ rbs_defined = defined?(::RBS) && ::RBS::VERSION.first == "3"
83
+
84
+ if resource_method_defined && rbs_defined
85
+ Anchor::Types::Inference::RBS.from(name.to_sym, resource_method)
86
+ elsif model_method_defined && rbs_defined
87
+ Anchor::Types::Inference::RBS.from(_model_class.name.to_sym, model_method.to_sym)
88
+ elsif column
83
89
  type = Anchor::Types::Inference::ActiveRecord::SQL.from(column)
84
90
 
85
91
  if enum
@@ -109,6 +115,12 @@ module Anchor
109
115
  else
110
116
  type
111
117
  end
118
+ elsif rbs_defined
119
+ # TODO: Methods may not be defined on the class at generation time?
120
+ [
121
+ Anchor::Types::Inference::RBS.from(name.to_sym, resource_method),
122
+ Anchor::Types::Inference::RBS.from(_model_class.name.to_sym, model_method.to_sym),
123
+ ].find { |t| t != Anchor::Types::Unknown } || Anchor::Types::Unknown
112
124
  else
113
125
  Anchor::Types::Unknown
114
126
  end
@@ -11,6 +11,7 @@ module Anchor::TypeScript
11
11
  when Anchor::Types::Null.singleton_class then "null"
12
12
  when Anchor::Types::Record, Anchor::Types::Record.singleton_class then "Record<string, #{type_string(type.try(:value_type) || Anchor::Types::Unknown)}>"
13
13
  when Anchor::Types::Union then type.types.map { |type| type_string(type, depth) }.join(" | ")
14
+ when Anchor::Types::Intersection then type.types.map { |type| "(#{type_string(type, depth)})" }.join(" & ")
14
15
  when Anchor::Types::Maybe then Anchor.config.maybe_as_union ? type_string(Anchor::Types::Union.new([type.type, Anchor::Types::Null]), depth) : "Maybe<#{type_string(type.type, depth)}>"
15
16
  when Anchor::Types::Array then Anchor.config.array_bracket_notation ? "(#{type_string(type.type, depth)})[]" : "Array<#{type_string(type.type, depth)}>"
16
17
  when Anchor::Types::Literal then serialize_literal(type.value)
@@ -0,0 +1,83 @@
1
+ module Anchor::Types::Inference
2
+ module RBS
3
+ class << self
4
+ # @param class_name [Symbol] e.g. :Exhaustive
5
+ # @param method_name [Symbol] e.g. :model_overridden
6
+ def from(class_name, method_name)
7
+ @loader ||= ::RBS::EnvironmentLoader.new.tap do |l|
8
+ l.add(path: Rails.root.join("sig"))
9
+ end
10
+
11
+ @env ||= ::RBS::Environment.from_loader(@loader).resolve_type_names
12
+
13
+ # TODO: Do we need both the absolute and non-absolute namespaces?
14
+ klass = @env.class_decls.keys.find { |kl| [class_name.to_s, "::#{class_name}"].include?(kl.to_s) }
15
+ return Types::Unknown unless klass
16
+
17
+ @builder ||= ::RBS::DefinitionBuilder.new(env: @env)
18
+ instance = @builder.build_instance(klass)
19
+
20
+ instance_method = instance.methods[method_name]
21
+ return Types::Unknown unless instance_method
22
+
23
+ method_types = instance.methods[method_name].method_types
24
+ return Types::Unknown unless method_types.length == 1
25
+
26
+ return_type = method_types.first.type.return_type
27
+ from_rbs_type(return_type)
28
+ end
29
+
30
+ private
31
+
32
+ def from_rbs_type(type)
33
+ case type
34
+ when ::RBS::Types::ClassInstance then from_class_instance(type)
35
+ when ::RBS::Types::Literal then Types::Literal.new(type.literal)
36
+ when ::RBS::Types::Bases::Bool then Types::Boolean
37
+ when ::RBS::Types::Bases::Nil then Types::Null
38
+ when ::RBS::Types::Bases::Void then Types::Unknown
39
+ when ::RBS::Types::Bases::Any then Types::Unknown
40
+ when ::RBS::Types::Optional then Types::Maybe.new(from_rbs_type(type.type))
41
+ when ::RBS::Types::Record then from_record(type)
42
+ when ::RBS::Types::Union then from_union(type)
43
+ when ::RBS::Types::Intersection then from_intersection(type)
44
+ when ::RBS::Types::Tuple then Types::Unknown # TODO
45
+ else Types::Unknown
46
+ end
47
+ end
48
+
49
+ def from_record(type)
50
+ properties = type.fields.map do |name, type|
51
+ Types::Property.new(name, from_rbs_type(type))
52
+ end
53
+ optional_properties = type.optional_fields.map do |name, type|
54
+ Types::Property.new(name, from_rbs_type(type), true)
55
+ end
56
+ Types::Object.new(properties + optional_properties)
57
+ end
58
+
59
+ def from_union(type)
60
+ types = type.types.map { |type| from_rbs_type(type) }
61
+ Types::Union.new(types)
62
+ end
63
+
64
+ def from_intersection(type)
65
+ types = type.types.map { |type| from_rbs_type(type) }
66
+ Types::Intersection.new(types)
67
+ end
68
+
69
+ def from_class_instance(type)
70
+ case type.name.to_s
71
+ when "::String" then Types::String
72
+ when "::Numeric" then Types::Float
73
+ when "::Integer" then Types::Integer
74
+ when "::Float" then Types::Float
75
+ when "::BigDecimal" then Types::String
76
+ when "::Boolean" then Types::Boolean
77
+ when "::Array" then Types::Array.new(from_rbs_type(type.args.first))
78
+ else Types::Unknown
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
data/lib/anchor/types.rb CHANGED
@@ -12,6 +12,7 @@ module Anchor
12
12
  Array = Struct.new(:type)
13
13
  Literal = Struct.new(:value)
14
14
  Union = Struct.new(:types)
15
+ Intersection = Struct.new(:types)
15
16
  Reference = Struct.new(:name) do
16
17
  def anchor_schema_name
17
18
  name
@@ -1,3 +1,3 @@
1
1
  module Anchor
2
- VERSION = "2.11.1"
2
+ VERSION = "2.12.0"
3
3
  end
@@ -12,6 +12,7 @@ require "anchor/concerns/schema_serializable"
12
12
  require "anchor/schema"
13
13
  require "anchor/types/inference/jsonapi"
14
14
  require "anchor/types/inference/active_record"
15
+ require "anchor/types/inference/rbs"
15
16
  require "anchor/type_script/file_structure"
16
17
  require "anchor/type_script/types"
17
18
  require "anchor/type_script/schema_generator"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-resources-anchor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.1
4
+ version: 2.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-26 00:00:00.000000000 Z
11
+ date: 2025-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jsonapi-resources
@@ -110,6 +110,7 @@ files:
110
110
  - lib/anchor/types.rb
111
111
  - lib/anchor/types/inference/active_record.rb
112
112
  - lib/anchor/types/inference/jsonapi.rb
113
+ - lib/anchor/types/inference/rbs.rb
113
114
  - lib/anchor/version.rb
114
115
  - lib/jsonapi-resources-anchor.rb
115
116
  homepage:
@@ -117,7 +118,7 @@ licenses:
117
118
  - MIT
118
119
  metadata:
119
120
  changelog_uri: https://github.com/mattkhan/jsonapi-resources-anchor/blob/main/CHANGELOG.md
120
- documentation_uri: https://anchor-gem.vercel.app/docs
121
+ documentation_uri: https://jsonapi-resources-anchor.up.railway.app/docs
121
122
  source_code_uri: https://github.com/mattkhan/jsonapi-resources-anchor
122
123
  github_repo: ssh://github.com/mattkhan/jsonapi-resources-anchor
123
124
  post_install_message: