protobufable 0.1.0 → 0.2.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: 5f133f23141bc2f8aef5ad8d1d0dd0f88dd58a51843d468d3b242cf0ec7a6d83
4
- data.tar.gz: f030966b166069c87390a9d962904fe363ab36a5a9b9531c66deb4e77c3a67cb
3
+ metadata.gz: e47657701ef1c828034181cc1bbc82a53445dec597c256ece0d574a088a59949
4
+ data.tar.gz: 80279d482e808aff6d938f5e791b8a20f56f97f4615019c55f938b9aedb43fce
5
5
  SHA512:
6
- metadata.gz: 6b3ea92d4a634aa17b4a67b2f612e6d5172c1de26184fb0f5462222f07553ed97091aaa21994f7f8e3c55ec49149aaf74597068e732b97e9f29c2d9af99180b1
7
- data.tar.gz: 4895b5014905f7e2e353f31fca6f8b76000560cf474602b0c2f8e3bafcc3efaedb74d15b5e39aa661c6bd6148f628093c6aa96a1469a9d70378dc8e96c5c222a
6
+ metadata.gz: f2b3025271f7476e546207c56fdd4e0c194436577a4b43cce6f14e64fb3d9805d79570035106f0c87be46455746a5c8f8b9c78b7871e8057468cfde66f7b309d
7
+ data.tar.gz: ef41c4a81f5b34389ba4b57c99941dff8755dec28f649501a1296a25d01510a0bcb8f133b3951746c0f6aff0c9b602022de89fb80a42b9280d476a0ffde1d6dd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 - 2026-11-05
4
+
5
+ - `Protobufable::JsonCoder` and `Protobufable::BinaryCoder` are `serialize` coders keeping a
6
+ message in a `text` column as ProtoJSON or in a `binary` column as wire format. A `json` or
7
+ `jsonb` column still takes `Protobufable::JsonType`; `JsonCoder` raises `Protobufable::Error`
8
+ on a row such a column hands back parsed.
9
+ - The Railtie registers the Alba `:timestamp` type on boot when Alba is loaded, unless the
10
+ application already registered a type by that name. Calling
11
+ `Protobufable::AlbaBinding.register_timestamp_type!` from an initializer is no longer needed.
12
+ - `Protobufable::AlbaBinding` extends the resource with `with_protobuf` and `message_class`
13
+ rather than installing them as an Alba helper. On Alba 4 they no longer reach resource
14
+ instances, where `message_class` shadowed an includer's own, and a resource's own
15
+ `helper do ... end` no longer adds methods to every bound resource.
16
+
3
17
  ## 0.1.0 - 2026-10-13
4
18
 
5
19
  Initial release.
data/DESIGN.md CHANGED
@@ -73,6 +73,10 @@ tracking would compare encoded text. `changed_in_place?` compares decoded messag
73
73
  `jsonb` column hands back a canonicalized document whose key order need not match what
74
74
  `encode_json` produced, which would otherwise read as a change on every load.
75
75
 
76
+ `JsonCoder` and `BinaryCoder` exist for columns the database does not treat as JSON: `text`, and
77
+ `binary` holding bytes such as a ciphertext. They are no answer for a `json` column, because
78
+ `serialize` runs the column's own JSON type around the coder.
79
+
76
80
  ## The problem catalogue
77
81
 
78
82
  `Problem::Detailable` documents an extension contract for exactly this: prepend a module to the
data/README.md CHANGED
@@ -76,8 +76,9 @@ render proto_json: Api::GetWidgetResponse.new(widget: WidgetResource.new(widget)
76
76
  ### Messages in a column
77
77
 
78
78
  `Protobufable::JsonType` keeps a message in a `json` or `jsonb` column, declared per attribute.
79
- It is an `ActiveModel` type, not a `serialize` coder, so dirty tracking and casting behave. See
80
- [docs/columns.md](docs/columns.md).
79
+ It is an `ActiveModel` type, not a `serialize` coder, so dirty tracking and casting behave. For a
80
+ `text` or `binary` column, `Protobufable::JsonCoder` and `Protobufable::BinaryCoder` are coders
81
+ for `serialize`. See [docs/columns.md](docs/columns.md).
81
82
 
82
83
  ```ruby
83
84
  class Widget < ApplicationRecord
data/docs/columns.md CHANGED
@@ -32,3 +32,26 @@ in SQL from telling absent from default.
32
32
 
33
33
  To run `buf.validate` rules over the column before save, see
34
34
  [Value validation](validation.md#stored-columns).
35
+
36
+ ## `text` and `binary` columns
37
+
38
+ A column that is not JSON to the database takes a `serialize` coder instead.
39
+
40
+ ```ruby
41
+ class Credential < ApplicationRecord
42
+ serialize :secret, coder: Protobufable::BinaryCoder.new(Internal::CredentialSecret)
43
+ serialize :settings, coder: Protobufable::JsonCoder.new(Internal::WidgetSettings)
44
+ end
45
+ ```
46
+
47
+ `BinaryCoder` stores the wire format, for a `binary` or `bytea` column or anything that holds
48
+ opaque bytes, such as a value encrypted before it is written. `JsonCoder` stores ProtoJSON in a
49
+ `text` column, reading and writing it as `JsonType` does, and takes the same
50
+ `preserve_proto_fieldnames:`. Neither casts from a Hash, and dirty tracking compares encoded
51
+ values. `ColumnValidatable` checks only `JsonType` columns.
52
+
53
+ `JsonCoder` does not work on a `json` or `jsonb` column. `serialize` layers a coder over the
54
+ column's own type, so the String the coder dumps is JSON-encoded a second time and stored as a
55
+ string literal, and a stored object reaches the coder already parsed into a Hash. `JsonCoder`
56
+ raises `Protobufable::Error` on the latter. Rails refuses only `coder: JSON` on such a column, so
57
+ nothing stops the declaration at boot.
data/docs/responses.md CHANGED
@@ -32,11 +32,49 @@ declare, and a field no attribute produces, each raise there rather than at resp
32
32
  every attribute inside the block — the check runs when `with_protobuf` does, so anything
33
33
  declared after it is never compared.
34
34
 
35
- `attributes created_at: :timestamp` needs the converter, because a `google.protobuf.Timestamp`
36
- field refuses the `ActiveSupport::TimeWithZone` an ActiveRecord column hands back:
35
+ ### Nested messages
36
+
37
+ A message field is an ordinary Alba association: `one` for a singular sub-message, `many` for a
38
+ repeated one, each with a resource bound to that sub-message.
39
+
40
+ ```ruby
41
+ class OwnerResource < ApplicationResource
42
+ include Protobufable::AlbaBinding
43
+
44
+ with_protobuf Api::Owner do
45
+ attributes :id, :name
46
+ end
47
+ end
48
+
49
+ class WidgetResource < ApplicationResource
50
+ include Protobufable::AlbaBinding
51
+
52
+ with_protobuf Api::Widget do
53
+ attributes :id
54
+ one :owner, resource: OwnerResource # Api::Owner owner = 2;
55
+ many :tags, resource: TagResource # repeated Api::Tag tags = 3;
56
+ end
57
+ end
58
+ ```
59
+
60
+ A `nil` association leaves the field unset. Each resource is checked against its own message
61
+ only: `WidgetResource` counts `owner` as one attribute and never looks inside it. Bind the
62
+ associated resource too. With an unbound resource or an inline `one :owner do ... end` block, a
63
+ stray attribute fails only at response time and a missing one comes back empty.
64
+
65
+ Keys must stay proto field names at every level, so a `transform_keys` or `root_key` on the
66
+ resource breaks the binding.
67
+
68
+ ### Timestamps
69
+
70
+ `attributes created_at: :timestamp` converts to `Time`, because a `google.protobuf.Timestamp`
71
+ field refuses the `ActiveSupport::TimeWithZone` an ActiveRecord column hands back.
72
+
73
+ The Railtie registers the `:timestamp` type on boot when Alba is loaded, unless the application
74
+ has already registered a type by that name. Alba's type registry is global, so outside Rails, or
75
+ after `Alba.reset!` in a test suite, register it yourself:
37
76
 
38
77
  ```ruby
39
- # config/initializers/protobufable.rb
40
78
  Protobufable::AlbaBinding.register_timestamp_type!
41
79
  ```
42
80
 
@@ -35,13 +35,11 @@ module Protobufable
35
35
  # @return [void]
36
36
  #: (untyped base) -> void
37
37
  def self.included(base)
38
- base.helper(HelperMethods)
38
+ # Alba's `helper` would also put the DSL on instances (since Alba 4) and adopt this module
39
+ # as the resource's helper, which a later `helper do ... end` then writes into.
40
+ base.extend(HelperMethods)
39
41
  end
40
42
 
41
- # Each of these reaches the binding through `self.class`: Alba installs HelperMethods on
42
- # instances too, so a bare `message_class` here would resolve to the class-level reader with
43
- # `self` being the instance, whose ivar is never set.
44
- #
45
43
  # @return [Object] the bound message, built from the serialized attributes
46
44
  #: () -> untyped
47
45
  def as_protobuf = self.class.message_class.new(as_json)
@@ -60,7 +58,7 @@ module Protobufable
60
58
  .encode_json(as_protobuf, preserve_proto_fieldnames: true, emit_defaults: false)
61
59
  end
62
60
 
63
- # Class-level DSL, installed through Alba's own helper mechanism.
61
+ # Class-level DSL.
64
62
  #
65
63
  # @rbs module-self _AlbaBindingClass
66
64
  module HelperMethods
@@ -114,12 +112,10 @@ module Protobufable
114
112
  # ActiveSupport::TimeWithZone, which is what an ActiveRecord timestamp column hands back,
115
113
  # so a resource serializing one needs the conversion.
116
114
  #
117
- # Protobufable::AlbaBinding.register_timestamp_type!
118
- #
119
115
  # attribute :created_at, :timestamp
120
116
  #
121
- # Opt-in rather than done on require: Alba's type registry is global, and a gem should not
122
- # add to it behind a host's back.
117
+ # The Railtie calls this on boot unless `:timestamp` is already registered. Outside Rails, or
118
+ # after `Alba.reset!`, call it directly.
123
119
  #
124
120
  # @return [void]
125
121
  #: () -> void
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ # Copyright 2026 Sorah Fukumori
5
+ # SPDX-License-Identifier: MIT
6
+
7
+ require "protobufable"
8
+
9
+ module Protobufable
10
+ # A `serialize` coder storing a protobuf message as its binary wire format, for a `binary` or
11
+ # `bytea` column.
12
+ #
13
+ # @example
14
+ # class Credential < ApplicationRecord
15
+ # serialize :secret, coder: Protobufable::BinaryCoder.new(Internal::CredentialSecret)
16
+ # end
17
+ class BinaryCoder
18
+ # @return [Class] the generated message class this column holds
19
+ attr_reader :message_class #: Google::Protobuf::_MessageClass
20
+
21
+ # @param message_class [Class] the generated message class this column holds
22
+ # @return [void]
23
+ #: (Google::Protobuf::_MessageClass message_class) -> void
24
+ def initialize(message_class)
25
+ @message_class = message_class
26
+ end
27
+
28
+ # @param bytes [String, nil] the stored bytes
29
+ # @return [Object, nil] the decoded message, or nil for a null column
30
+ #: (String? bytes) -> untyped
31
+ def load(bytes)
32
+ return if bytes.nil?
33
+
34
+ @message_class.decode(bytes)
35
+ end
36
+
37
+ # @param message [Object, nil] the message to store
38
+ # @return [String, nil] the encoded bytes, or nil
39
+ #: (untyped message) -> String?
40
+ def dump(message)
41
+ return if message.nil?
42
+
43
+ @message_class.encode(message)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ # Copyright 2026 Sorah Fukumori
5
+ # SPDX-License-Identifier: MIT
6
+
7
+ require "protobufable"
8
+
9
+ module Protobufable
10
+ # A `serialize` coder storing a protobuf message as ProtoJSON in a `text` column.
11
+ #
12
+ # It cannot serve a `json` or `jsonb` column. `serialize` layers the coder over the column's
13
+ # own type, which encodes the String {#dump} returns a second time, storing a JSON string
14
+ # literal, and parses a stored object into a Hash before {#load} sees it. Use {JsonType}.
15
+ #
16
+ # @example
17
+ # class Widget < ApplicationRecord
18
+ # serialize :settings, coder: Protobufable::JsonCoder.new(Internal::WidgetSettings)
19
+ # end
20
+ class JsonCoder
21
+ # @return [Class] the generated message class this column holds
22
+ attr_reader :message_class #: Google::Protobuf::_MessageClass
23
+
24
+ # @param message_class [Class] the generated message class this column holds
25
+ # @param preserve_proto_fieldnames [Boolean] whether documents are written with the
26
+ # `.proto` field names (`snake_case`) rather than their lowerCamelCase JSON names
27
+ # @return [void]
28
+ #: (Google::Protobuf::_MessageClass message_class, ?preserve_proto_fieldnames: bool) -> void
29
+ def initialize(message_class, preserve_proto_fieldnames: false)
30
+ @message_class = message_class
31
+ @preserve_proto_fieldnames = preserve_proto_fieldnames
32
+ end
33
+
34
+ # Decodes a stored document, tolerating unknown fields as {JsonType#deserialize} does.
35
+ #
36
+ # @param json [String, nil] the stored document
37
+ # @return [Object, nil] the decoded message, or nil for a null column
38
+ # @raise [Error] when handed an already parsed document, as a json column does
39
+ #: (untyped json) -> untyped
40
+ def load(json)
41
+ return if json.nil?
42
+
43
+ unless json.is_a?(::String)
44
+ raise Error,
45
+ "#{self.class} received a #{json.class} rather than a String; " \
46
+ "a json or jsonb column needs Protobufable::JsonType instead"
47
+ end
48
+
49
+ @message_class.decode_json(json, ignore_unknown_fields: true)
50
+ end
51
+
52
+ # Encodes a message, emitting defaults as {JsonType#serialize} does.
53
+ #
54
+ # @param message [Object, nil] the message to store
55
+ # @return [String, nil] the document to write, or nil
56
+ #: (untyped message) -> String?
57
+ def dump(message)
58
+ return if message.nil?
59
+
60
+ @message_class.encode_json(
61
+ message,
62
+ emit_defaults: true,
63
+ preserve_proto_fieldnames: @preserve_proto_fieldnames,
64
+ )
65
+ end
66
+ end
67
+ end
@@ -10,8 +10,8 @@ require "action_dispatch/railtie"
10
10
  require "protobufable"
11
11
 
12
12
  module Protobufable
13
- # Installs the renderers and the request body parser on boot, and classifies a broken
14
- # `buf.validate` rule as a 400.
13
+ # Installs the renderers and the request body parser on boot, classifies a broken
14
+ # `buf.validate` rule as a 400, and registers the Alba `:timestamp` type when Alba is loaded.
15
15
  class Railtie < ::Rails::Railtie
16
16
  # A string, so protovalidate stays unloaded for an application that does not use it.
17
17
  # `config.action_dispatch` is answered by method_missing, which RBS cannot describe.
@@ -22,5 +22,15 @@ module Protobufable
22
22
  initializer "protobufable.install" do
23
23
  Protobufable.install!
24
24
  end
25
+
26
+ # Leaves a `:timestamp` type the application registered itself in place.
27
+ initializer "protobufable.alba" do
28
+ next unless defined?(::Alba)
29
+
30
+ ::Alba.find_type(:timestamp)
31
+ rescue ::Alba::UnsupportedType
32
+ require "protobufable/alba_binding"
33
+ Protobufable::AlbaBinding.register_timestamp_type!
34
+ end
25
35
  end
26
36
  end
@@ -6,5 +6,5 @@
6
6
 
7
7
  module Protobufable
8
8
  # The gem's version.
9
- VERSION = "0.1.0" #: String
9
+ VERSION = "0.2.0" #: String
10
10
  end
data/lib/protobufable.rb CHANGED
@@ -9,6 +9,8 @@ require "google/protobuf/well_known_types"
9
9
 
10
10
  require "protobufable/version"
11
11
  require "protobufable/json_type"
12
+ require "protobufable/json_coder"
13
+ require "protobufable/binary_coder"
12
14
  require "protobufable/request_parseable"
13
15
  require "protobufable/renderers"
14
16
 
@@ -28,10 +28,6 @@ module Protobufable
28
28
  # : (untyped base) -> void
29
29
  def self.included: (untyped base) -> void
30
30
 
31
- # Each of these reaches the binding through `self.class`: Alba installs HelperMethods on
32
- # instances too, so a bare `message_class` here would resolve to the class-level reader with
33
- # `self` being the instance, whose ivar is never set.
34
- #
35
31
  # @return [Object] the bound message, built from the serialized attributes
36
32
  # : () -> untyped
37
33
  def as_protobuf: () -> untyped
@@ -47,7 +43,7 @@ module Protobufable
47
43
  # : (*untyped) -> String
48
44
  def to_json: (*untyped) -> String
49
45
 
50
- # Class-level DSL, installed through Alba's own helper mechanism.
46
+ # Class-level DSL.
51
47
  #
52
48
  # @rbs module-self _AlbaBindingClass
53
49
  module HelperMethods : _AlbaBindingClass
@@ -77,12 +73,10 @@ module Protobufable
77
73
  # ActiveSupport::TimeWithZone, which is what an ActiveRecord timestamp column hands back,
78
74
  # so a resource serializing one needs the conversion.
79
75
  #
80
- # Protobufable::AlbaBinding.register_timestamp_type!
81
- #
82
76
  # attribute :created_at, :timestamp
83
77
  #
84
- # Opt-in rather than done on require: Alba's type registry is global, and a gem should not
85
- # add to it behind a host's back.
78
+ # The Railtie calls this on boot unless `:timestamp` is already registered. Outside Rails, or
79
+ # after `Alba.reset!`, call it directly.
86
80
  #
87
81
  # @return [void]
88
82
  # : () -> void
@@ -0,0 +1,30 @@
1
+ # Generated from lib/protobufable/binary_coder.rb with RBS::Inline
2
+
3
+ module Protobufable
4
+ # A `serialize` coder storing a protobuf message as its binary wire format, for a `binary` or
5
+ # `bytea` column.
6
+ #
7
+ # @example
8
+ # class Credential < ApplicationRecord
9
+ # serialize :secret, coder: Protobufable::BinaryCoder.new(Internal::CredentialSecret)
10
+ # end
11
+ class BinaryCoder
12
+ # @return [Class] the generated message class this column holds
13
+ attr_reader message_class: Google::Protobuf::_MessageClass
14
+
15
+ # @param message_class [Class] the generated message class this column holds
16
+ # @return [void]
17
+ # : (Google::Protobuf::_MessageClass message_class) -> void
18
+ def initialize: (Google::Protobuf::_MessageClass message_class) -> void
19
+
20
+ # @param bytes [String, nil] the stored bytes
21
+ # @return [Object, nil] the decoded message, or nil for a null column
22
+ # : (String? bytes) -> untyped
23
+ def load: (String? bytes) -> untyped
24
+
25
+ # @param message [Object, nil] the message to store
26
+ # @return [String, nil] the encoded bytes, or nil
27
+ # : (untyped message) -> String?
28
+ def dump: (untyped message) -> String?
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ # Generated from lib/protobufable/json_coder.rb with RBS::Inline
2
+
3
+ module Protobufable
4
+ # A `serialize` coder storing a protobuf message as ProtoJSON in a `text` column.
5
+ #
6
+ # It cannot serve a `json` or `jsonb` column. `serialize` layers the coder over the column's
7
+ # own type, which encodes the String {#dump} returns a second time, storing a JSON string
8
+ # literal, and parses a stored object into a Hash before {#load} sees it. Use {JsonType}.
9
+ #
10
+ # @example
11
+ # class Widget < ApplicationRecord
12
+ # serialize :settings, coder: Protobufable::JsonCoder.new(Internal::WidgetSettings)
13
+ # end
14
+ class JsonCoder
15
+ # @return [Class] the generated message class this column holds
16
+ attr_reader message_class: Google::Protobuf::_MessageClass
17
+
18
+ # @param message_class [Class] the generated message class this column holds
19
+ # @param preserve_proto_fieldnames [Boolean] whether documents are written with the
20
+ # `.proto` field names (`snake_case`) rather than their lowerCamelCase JSON names
21
+ # @return [void]
22
+ # : (Google::Protobuf::_MessageClass message_class, ?preserve_proto_fieldnames: bool) -> void
23
+ def initialize: (Google::Protobuf::_MessageClass message_class, ?preserve_proto_fieldnames: bool) -> void
24
+
25
+ # Decodes a stored document, tolerating unknown fields as {JsonType#deserialize} does.
26
+ #
27
+ # @param json [String, nil] the stored document
28
+ # @return [Object, nil] the decoded message, or nil for a null column
29
+ # @raise [Error] when handed an already parsed document, as a json column does
30
+ # : (untyped json) -> untyped
31
+ def load: (untyped json) -> untyped
32
+
33
+ # Encodes a message, emitting defaults as {JsonType#serialize} does.
34
+ #
35
+ # @param message [Object, nil] the message to store
36
+ # @return [String, nil] the document to write, or nil
37
+ # : (untyped message) -> String?
38
+ def dump: (untyped message) -> String?
39
+ end
40
+ end
@@ -1,8 +1,8 @@
1
1
  # Generated from lib/protobufable/railtie.rb with RBS::Inline
2
2
 
3
3
  module Protobufable
4
- # Installs the renderers and the request body parser on boot, and classifies a broken
5
- # `buf.validate` rule as a 400.
4
+ # Installs the renderers and the request body parser on boot, classifies a broken
5
+ # `buf.validate` rule as a 400, and registers the Alba `:timestamp` type when Alba is loaded.
6
6
  class Railtie < ::Rails::Railtie
7
7
  end
8
8
  end
@@ -2,6 +2,10 @@
2
2
  # is declared, and the resource DSL stays untyped: it is Alba's to describe, not ours.
3
3
  module Alba
4
4
  def self.register_type: (Symbol name, converter: untyped, ?auto_convert: bool) -> void
5
+ def self.find_type: (Symbol name) -> untyped
6
+
7
+ class UnsupportedType < StandardError
8
+ end
5
9
 
6
10
  module Resource
7
11
  end
@@ -21,7 +25,6 @@ module Protobufable
21
25
  def message_class: () -> Google::Protobuf::_MessageClass
22
26
  def name: () -> String?
23
27
  def module_eval: () { () -> void } -> untyped
24
- def helper: (Module) -> void
25
28
  def instance_variable_get: (Symbol) -> untyped
26
29
  def class_eval: () { () -> void } -> untyped
27
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobufable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sorah Fukumori
@@ -241,10 +241,12 @@ files:
241
241
  - lib/protobufable.rb
242
242
  - lib/protobufable/alba_binding.rb
243
243
  - lib/protobufable/bad_request.rb
244
+ - lib/protobufable/binary_coder.rb
244
245
  - lib/protobufable/column_validatable.rb
245
246
  - lib/protobufable/connect.rb
246
247
  - lib/protobufable/connect/problem_rescuable.rb
247
248
  - lib/protobufable/field_path.rb
249
+ - lib/protobufable/json_coder.rb
248
250
  - lib/protobufable/json_type.rb
249
251
  - lib/protobufable/problem.rb
250
252
  - lib/protobufable/problem/information.rb
@@ -264,10 +266,12 @@ files:
264
266
  - sig/generated/protobufable.rbs
265
267
  - sig/generated/protobufable/alba_binding.rbs
266
268
  - sig/generated/protobufable/bad_request.rbs
269
+ - sig/generated/protobufable/binary_coder.rbs
267
270
  - sig/generated/protobufable/column_validatable.rbs
268
271
  - sig/generated/protobufable/connect.rbs
269
272
  - sig/generated/protobufable/connect/problem_rescuable.rbs
270
273
  - sig/generated/protobufable/field_path.rbs
274
+ - sig/generated/protobufable/json_coder.rbs
271
275
  - sig/generated/protobufable/json_type.rbs
272
276
  - sig/generated/protobufable/problem.rbs
273
277
  - sig/generated/protobufable/problem/information.rbs