proto_turf 0.0.2 → 0.0.3

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: a059f77cfc5a504cf09140a84a578a3609ef40c83074897f8dda0eb42bcc011e
4
- data.tar.gz: 1f0156bec33ddd18a48d90a3500b20066bf3a99a57627ef5a811e4efe439a60f
3
+ metadata.gz: 9af9eb4df4dd0323090363e65378d08d4b9a55050eb0a08ea6ddfe2cd7bd8b59
4
+ data.tar.gz: 32fb8b5f560d5e49978930f5e863d5851efc17b288f75c26e45ee7d1cf8e98dd
5
5
  SHA512:
6
- metadata.gz: 6d7d01d659d17256f3cb3bcba5abb9a1b5634c0e423cb7a0b603855ddbd3c26abb882ca8ae23e651fa5b1e7d39286ff024933fb31c058b57a6077d5b6a4f37ae
7
- data.tar.gz: eab1c0e1e9b220a1eb1a9adf2b969adde64298d248816faffa9ed96f15d0ca565997d9d7e201f8d4fef5fe7cf3d128d971720b3393532fb083704bf1ca640774
6
+ metadata.gz: 3286859be78192d3495c3dc58e15dad50273aed4d611ddf579b9b27a16b01bbf0652d17af367192ed6dd9154a693a1991342439d53bde14777a5e61e5402a036
7
+ data.tar.gz: e8d941d3a7b153345e407ed62fb4e6201b93a65e01810f06cacb4fa616bbbf3c93b1456be349f3f53fd8e41d5a7f4fc4fcd0fad9fc380f8c7ff4ea101678fc18
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/CHANGELOG.md CHANGED
@@ -7,6 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
- # 0.0.2 - 2025-8-14
10
+ # 0.0.3 - 2025-8-15
11
11
 
12
12
  * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,106 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ proto_turf (0.0.2)
5
+ excon
6
+ google-protobuf
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ addressable (2.8.7)
12
+ public_suffix (>= 2.0.2, < 7.0)
13
+ ast (2.4.3)
14
+ bigdecimal (3.2.2)
15
+ crack (1.0.0)
16
+ bigdecimal
17
+ rexml
18
+ diff-lcs (1.6.1)
19
+ excon (1.2.9)
20
+ logger
21
+ google-protobuf (4.30.2-arm64-darwin)
22
+ bigdecimal
23
+ rake (>= 13)
24
+ hashdiff (1.2.0)
25
+ json (2.13.2)
26
+ language_server-protocol (3.17.0.5)
27
+ lint_roller (1.1.0)
28
+ logger (1.7.0)
29
+ parallel (1.27.0)
30
+ parser (3.3.9.0)
31
+ ast (~> 2.4.1)
32
+ racc
33
+ prism (1.4.0)
34
+ public_suffix (6.0.2)
35
+ racc (1.8.1)
36
+ rainbow (3.1.1)
37
+ rake (13.3.0)
38
+ regexp_parser (2.11.2)
39
+ rexml (3.4.1)
40
+ rspec (3.13.0)
41
+ rspec-core (~> 3.13.0)
42
+ rspec-expectations (~> 3.13.0)
43
+ rspec-mocks (~> 3.13.0)
44
+ rspec-core (3.13.3)
45
+ rspec-support (~> 3.13.0)
46
+ rspec-expectations (3.13.4)
47
+ diff-lcs (>= 1.2.0, < 2.0)
48
+ rspec-support (~> 3.13.0)
49
+ rspec-mocks (3.13.3)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.13.0)
52
+ rspec-support (3.13.3)
53
+ rubocop (1.75.8)
54
+ json (~> 2.3)
55
+ language_server-protocol (~> 3.17.0.2)
56
+ lint_roller (~> 1.1.0)
57
+ parallel (~> 1.10)
58
+ parser (>= 3.3.0.2)
59
+ rainbow (>= 2.2.2, < 4.0)
60
+ regexp_parser (>= 2.9.3, < 3.0)
61
+ rubocop-ast (>= 1.44.0, < 2.0)
62
+ ruby-progressbar (~> 1.7)
63
+ unicode-display_width (>= 2.4.0, < 4.0)
64
+ rubocop-ast (1.46.0)
65
+ parser (>= 3.3.7.2)
66
+ prism (~> 1.4)
67
+ rubocop-performance (1.25.0)
68
+ lint_roller (~> 1.1)
69
+ rubocop (>= 1.75.0, < 2.0)
70
+ rubocop-ast (>= 1.38.0, < 2.0)
71
+ ruby-progressbar (1.13.0)
72
+ standard (1.50.0)
73
+ language_server-protocol (~> 3.17.0.2)
74
+ lint_roller (~> 1.0)
75
+ rubocop (~> 1.75.5)
76
+ standard-custom (~> 1.0.0)
77
+ standard-performance (~> 1.8)
78
+ standard-custom (1.0.2)
79
+ lint_roller (~> 1.0)
80
+ rubocop (~> 1.50)
81
+ standard-performance (1.8.0)
82
+ lint_roller (~> 1.1)
83
+ rubocop-performance (~> 1.25.0)
84
+ standardrb (1.0.1)
85
+ standard
86
+ unicode-display_width (3.1.5)
87
+ unicode-emoji (~> 4.0, >= 4.0.4)
88
+ unicode-emoji (4.0.4)
89
+ webmock (3.25.1)
90
+ addressable (>= 2.8.0)
91
+ crack (>= 0.3.2)
92
+ hashdiff (>= 0.4.0, < 2.0.0)
93
+
94
+ PLATFORMS
95
+ arm64-darwin
96
+
97
+ DEPENDENCIES
98
+ bundler (~> 2.0)
99
+ proto_turf!
100
+ rake (~> 13.0)
101
+ rspec (~> 3.2)
102
+ standardrb
103
+ webmock
104
+
105
+ BUNDLED WITH
106
+ 2.6.7
data/README.md CHANGED
@@ -27,7 +27,7 @@ Example usage:
27
27
  ```ruby
28
28
  require 'proto_turf'
29
29
 
30
- proto_turf = ProtoTurf.new(registry_url: 'http://localhost:8081')
30
+ proto_turf = ProtoTurf.new(registry_url: 'http://localhost:8081', schema_paths: ['path/to/protos'])
31
31
  message = MyProto::MyMessage.new(field1: 'value1', field2: 42)
32
32
  encoded = proto_turf.encode(message, subject: 'my-subject')
33
33
 
@@ -38,7 +38,15 @@ decoded_proto_message = proto_turf.decode(encoded_string)
38
38
 
39
39
  If you're using [buf](https://buf.build/) to manage your Protobuf definitions, you should run `buf export` before using `proto_turf` to ensure that all the dependencies are available as `.proto` files in your project. The actual proto text is needed when registering the schema with the Schema Registry.
40
40
 
41
+ Because `buf export` overwrites/deletes existing files, you should run it into a different directory and provide both as `schema_paths` to the `ProtoTurf` constructor.
42
+
41
43
  ## Notes about usage
42
44
 
43
45
  * When decoding, this library does *not* attempt to fully parse the Proto definition stored on the schema registry and generate dynamic classes. Instead, it simply parses out the package and message and assumes that the reader has the message available in the descriptor pool. Any compatibility issues should be detected through normal means, i.e. just by instantiating the message and seeing if any errors are raised.
44
46
 
47
+ ### Regenerating test protos
48
+ Run the following to regenerate:
49
+
50
+ ```sh
51
+ protoc -I spec/schemas --ruby_out=spec/gen --ruby_opt=paths=source_relative spec/schemas/**/*.proto
52
+ ```
@@ -1,5 +1,4 @@
1
1
  class ProtoTurf::CachedConfluentSchemaRegistry
2
-
3
2
  # @param upstream [ProtoTurf::ConfluentSchemaRegistry]
4
3
  def initialize(upstream)
5
4
  @upstream = upstream
@@ -9,7 +8,7 @@ class ProtoTurf::CachedConfluentSchemaRegistry
9
8
  end
10
9
 
11
10
  # Delegate the following methods to the upstream
12
- %i(subject_versions schema_subject_versions).each do |name|
11
+ %i[subject_versions schema_subject_versions].each do |name|
13
12
  define_method(name) do |*args|
14
13
  instance_variable_get(:@upstream).send(name, *args)
15
14
  end
@@ -29,14 +28,14 @@ class ProtoTurf::CachedConfluentSchemaRegistry
29
28
  return @versions_by_subject_and_id[key] if @versions_by_subject_and_id[key]
30
29
 
31
30
  results = @upstream.schema_subject_versions(id)
32
- @versions_by_subject_and_id[key] = results&.find { |r| r['subject'] == subject }&.dig('version')
31
+ @versions_by_subject_and_id[key] = results&.find { |r| r["subject"] == subject }&.dig("version")
33
32
  end
34
33
 
35
34
  # @param subject [String] the subject to check
36
35
  # @param schema [String] the schema text to check
37
36
  # @return [Boolean] true if we know the schema has been registered for that subject.
38
37
  def registered?(subject, schema)
39
- @ids_by_schema[[subject, schema]].present?
38
+ @ids_by_schema[[subject, schema]] && !@ids_by_schema[[subject, schema]].empty?
40
39
  end
41
40
 
42
41
  # @param subject [String] the subject to register the schema under
@@ -47,5 +46,4 @@ class ProtoTurf::CachedConfluentSchemaRegistry
47
46
 
48
47
  @ids_by_schema[key] ||= @upstream.register(subject, schema, references: references)
49
48
  end
50
-
51
49
  end
@@ -1,8 +1,7 @@
1
- require 'excon'
1
+ require "excon"
2
2
 
3
3
  class ProtoTurf
4
4
  class ConfluentSchemaRegistry
5
-
6
5
  CONTENT_TYPE = "application/vnd.schemaregistry.v1+json".freeze
7
6
 
8
7
  def initialize(
@@ -24,7 +23,7 @@ class ProtoTurf
24
23
  retry_limit: nil
25
24
  )
26
25
  @path_prefix = path_prefix
27
- @schema_context_prefix = schema_context.nil? ? '' : ":.#{schema_context}:"
26
+ @schema_context_prefix = schema_context.nil? ? "" : ":.#{schema_context}:"
28
27
  @schema_context_options = schema_context.nil? ? {} : {query: {subject: @schema_context_prefix}}
29
28
  @logger = logger
30
29
  headers = Excon.defaults[:headers].merge(
@@ -57,7 +56,7 @@ class ProtoTurf
57
56
  # @return [String] the schema string stored in the registry for the given id
58
57
  def fetch(id)
59
58
  @logger.info "Fetching schema with id #{id}"
60
- data = get("/schemas/ids/#{id}", idempotent: true, **@schema_context_options, )
59
+ data = get("/schemas/ids/#{id}", idempotent: true, **@schema_context_options)
61
60
  data.fetch("schema")
62
61
  end
63
62
 
@@ -73,9 +72,9 @@ class ProtoTurf
73
72
  # @return [Integer] the ID of the registered schema
74
73
  def register(subject, schema, references: [])
75
74
  data = post("/subjects/#{@schema_context_prefix}#{CGI.escapeURIComponent(subject)}/versions",
76
- body: { schemaType: 'PROTOBUF',
77
- references: references,
78
- schema: schema.to_s }.to_json)
75
+ body: {schemaType: "PROTOBUF",
76
+ references: references,
77
+ schema: schema.to_s}.to_json)
79
78
 
80
79
  id = data.fetch("id")
81
80
 
@@ -105,7 +104,7 @@ class ProtoTurf
105
104
  end
106
105
 
107
106
  def request(path, **options)
108
- options = { expects: 200 }.merge!(options)
107
+ options = {expects: 200}.merge!(options)
109
108
  path = File.join(@path_prefix, path) unless @path_prefix.nil?
110
109
  response = @connection.request(path: path, **options)
111
110
  JSON.parse(response.body)
@@ -113,6 +112,5 @@ class ProtoTurf
113
112
  @logger.error("Error while requesting #{path}: #{e.response.body}")
114
113
  raise
115
114
  end
116
-
117
115
  end
118
116
  end
@@ -1,3 +1,3 @@
1
1
  class ProtoTurf
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/proto_turf.rb CHANGED
@@ -1,6 +1,10 @@
1
- require 'logger'
2
- require 'proto_turf/confluent_schema_registry'
3
- require 'proto_turf/cached_confluent_schema_registry'
1
+ require "logger"
2
+ require "google/protobuf"
3
+ require "google/protobuf/well_known_types"
4
+ require "google/protobuf/descriptor_pb"
5
+ require "json"
6
+ require "proto_turf/confluent_schema_registry"
7
+ require "proto_turf/cached_confluent_schema_registry"
4
8
 
5
9
  class ProtoTurf
6
10
  # Provides a way to encode and decode messages without having to embed schemas
@@ -15,14 +19,13 @@ class ProtoTurf
15
19
  # https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format
16
20
  MAGIC_BYTE = [0].pack("C").freeze
17
21
 
18
-
19
22
  # Instantiate a new ProtoTurf instance with the given configuration.
20
23
  #
21
24
  # registry - A schema registry object that responds to all methods in the
22
25
  # ProtoTurf::ConfluentSchemaRegistry interface.
23
26
  # registry_url - The String URL of the schema registry that should be used.
24
27
  # schema_context - Schema registry context name (optional)
25
- # schemas_path - The String file system path where local schemas are stored.
28
+ # schema_paths - The String file system path where local schemas are stored.
26
29
  # registry_path_prefix - The String URL path prefix used to namespace schema registry requests (optional).
27
30
  # logger - The Logger that should be used to log information (optional).
28
31
  # proxy - Forward the request via proxy (optional).
@@ -40,7 +43,7 @@ class ProtoTurf
40
43
  registry: nil,
41
44
  registry_url: nil,
42
45
  schema_context: nil,
43
- schemas_path: nil,
46
+ schema_paths: nil,
44
47
  registry_path_prefix: nil,
45
48
  logger: nil,
46
49
  proxy: nil,
@@ -57,7 +60,7 @@ class ProtoTurf
57
60
  retry_limit: nil
58
61
  )
59
62
  @logger = logger || Logger.new($stderr)
60
- @path = schemas_path
63
+ @paths = Array(schema_paths)
61
64
  @registry = registry || ProtoTurf::CachedConfluentSchemaRegistry.new(
62
65
  ProtoTurf::ConfluentSchemaRegistry.new(
63
66
  registry_url,
@@ -101,7 +104,7 @@ class ProtoTurf
101
104
  stream.write([id].pack("N"))
102
105
 
103
106
  _, indexes = find_index(message.class.descriptor.to_proto,
104
- file_descriptor.to_proto.message_type)
107
+ file_descriptor.to_proto.message_type)
105
108
 
106
109
  if indexes == [0]
107
110
  write_int(stream, 0)
@@ -138,7 +141,7 @@ class ProtoTurf
138
141
  end
139
142
 
140
143
  # The schema id is a 4-byte big-endian integer.
141
- schema_id = stream.read(4).unpack("N").first
144
+ schema_id = stream.read(4).unpack1("N")
142
145
 
143
146
  # For now, we're only going to support a single message per schema. See
144
147
  # https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format
@@ -161,7 +164,7 @@ class ProtoTurf
161
164
 
162
165
  private
163
166
 
164
- def find_index(descriptor, messages, indexes=[])
167
+ def find_index(descriptor, messages, indexes = [])
165
168
  messages.each_with_index do |sub_descriptor, i|
166
169
  if sub_descriptor == descriptor
167
170
  indexes.push(i)
@@ -221,7 +224,7 @@ class ProtoTurf
221
224
  raise "Could not find schema for #{full_name}. Make sure the corresponding .proto file has been compiled and loaded."
222
225
  end
223
226
  path = find_descriptor(indexes, descriptor.file_descriptor.to_proto.message_type)
224
- correct_message = Google::Protobuf::DescriptorPool.generated_pool.lookup("#{package}.#{path.join('.')}")
227
+ correct_message = Google::Protobuf::DescriptorPool.generated_pool.lookup("#{package}.#{path.join(".")}")
225
228
  correct_message.msgclass.decode(encoded)
226
229
  end
227
230
 
@@ -230,7 +233,7 @@ class ProtoTurf
230
233
  return if @registry.registered?(file_descriptor.name, subject)
231
234
 
232
235
  # register dependencies first
233
- dependencies = file_descriptor.to_proto.dependency.to_a.reject { |d| d.start_with?('google/protobuf/') }
236
+ dependencies = file_descriptor.to_proto.dependency.to_a.reject { |d| d.start_with?("google/protobuf/") }
234
237
  versions = dependencies.map do |dependency|
235
238
  dependency_descriptor = @all_schemas[dependency]
236
239
  result = register_schema(dependency_descriptor, subject: dependency_descriptor.name)
@@ -238,20 +241,22 @@ class ProtoTurf
238
241
  end
239
242
 
240
243
  @registry.register(subject,
241
- schema_text(file_descriptor),
242
- references: dependencies.map.with_index do |dependency, i|
243
- {
244
- name: dependency,
245
- subject: dependency,
246
- version: versions[i]
247
- }
248
- end
249
- )
244
+ schema_text(file_descriptor),
245
+ references: dependencies.map.with_index do |dependency, i|
246
+ {
247
+ name: dependency,
248
+ subject: dependency,
249
+ version: versions[i]
250
+ }
251
+ end)
250
252
  end
251
253
 
252
254
  def schema_text(file_descriptor)
253
- filename = "#{@path}/#{file_descriptor.name}"
254
- File.exist?(filename) ? File.read(filename) : ""
255
+ @paths.each do |path|
256
+ filename = "#{path}/#{file_descriptor.name}"
257
+ return File.read(filename) if File.exist?(filename)
258
+ end
259
+ ""
255
260
  end
256
261
 
257
262
  def load_schemas!
@@ -261,10 +266,9 @@ class ProtoTurf
261
266
  all_messages.each do |m|
262
267
  file_desc = m.descriptor.file_descriptor
263
268
  file_path = file_desc.name
264
- next if file_path.start_with?('google/protobuf/') # skip built-in protos
269
+ next if file_path.start_with?("google/protobuf/") # skip built-in protos
265
270
 
266
271
  @all_schemas[file_path] = file_desc
267
272
  end
268
273
  end
269
-
270
274
  end
data/proto_turf.gemspec CHANGED
@@ -1,27 +1,28 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path("../lib", __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'proto_turf/version'
3
+ require "proto_turf/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "proto_turf"
8
- spec.version = ProtoTurf::VERSION
9
- spec.authors = ["Daniel Orner"]
10
- spec.email = ["daniel.orner@flipp.com"]
11
- spec.summary = "Support for Protobuf files in Confluent Schema Registry"
12
- spec.homepage = "https://github.com/flipp-oss/proto_turf"
13
- spec.license = "MIT"
6
+ spec.name = "proto_turf"
7
+ spec.version = ProtoTurf::VERSION
8
+ spec.authors = ["Daniel Orner"]
9
+ spec.email = ["daniel.orner@flipp.com"]
10
+ spec.summary = "Support for Protobuf files in Confluent Schema Registry"
11
+ spec.homepage = "https://github.com/flipp-oss/proto_turf"
12
+ spec.license = "MIT"
14
13
 
15
14
  spec.metadata["rubygems_mfa_required"] = "true"
16
15
 
17
- spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
18
  spec.require_paths = ["lib"]
21
19
 
22
20
  spec.add_dependency "google-protobuf"
21
+ spec.add_dependency "excon"
23
22
 
24
23
  spec.add_development_dependency "bundler", "~> 2.0"
25
24
  spec.add_development_dependency "rake", "~> 13.0"
26
25
  spec.add_development_dependency "rspec", "~> 3.2"
26
+ spec.add_development_dependency "webmock"
27
+ spec.add_development_dependency "standardrb"
27
28
  end
@@ -0,0 +1,37 @@
1
+ RSpec.describe "encoding" do
2
+ let(:proto_turf) do
3
+ ProtoTurf.new(
4
+ registry_url: "http://localhost:8081",
5
+ schema_paths: ["spec/schemas"]
6
+ )
7
+ end
8
+
9
+ it "should decode a simple message" do
10
+ schema = File.read("#{__dir__}/schemas/simple/simple.proto")
11
+ stub = stub_request(:get, "http://localhost:8081/schemas/ids/15")
12
+ .to_return_json(body: {schema: schema})
13
+ msg = Simple::V1::SimpleMessage.new(name: "my name")
14
+ encoded = "\u0000\u0000\u0000\u0000\u000F\u0000" + msg.to_proto
15
+ expect(proto_turf.decode(encoded)).to eq(msg)
16
+
17
+ # if we do it again we should not see any more requests
18
+ expect(proto_turf.decode(encoded)).to eq(msg)
19
+
20
+ expect(stub).to have_been_requested.once
21
+ end
22
+
23
+ it "should decode a complex message" do
24
+ schema = File.read("#{__dir__}/schemas/referenced/referer.proto")
25
+ stub = stub_request(:get, "http://localhost:8081/schemas/ids/20")
26
+ .to_return_json(body: {schema: schema})
27
+ msg = Referenced::V1::MessageB::MessageBA.new(
28
+ simple: Simple::V1::SimpleMessage.new(name: "my name")
29
+ )
30
+ encoded = "\u0000\u0000\u0000\u0000\u0014\u0004\u0002\u0000" + msg.to_proto
31
+ expect(proto_turf.decode(encoded)).to eq(msg)
32
+
33
+ # if we do it again we should not see any more requests
34
+ expect(proto_turf.decode(encoded)).to eq(msg)
35
+ expect(stub).to have_been_requested.once
36
+ end
37
+ end
@@ -0,0 +1,58 @@
1
+ RSpec.describe "encoding" do
2
+ let(:proto_turf) do
3
+ ProtoTurf.new(
4
+ registry_url: "http://localhost:8081",
5
+ schema_paths: ["spec/schemas"]
6
+ )
7
+ end
8
+
9
+ it "should encode a simple message" do
10
+ schema = File.read("#{__dir__}/schemas/simple/simple.proto")
11
+ stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
12
+ .with(body: {"schemaType" => "PROTOBUF",
13
+ "references" => [],
14
+ "schema" => schema}).to_return_json(body: {id: 15})
15
+ msg = Simple::V1::SimpleMessage.new(name: "my name")
16
+ encoded = proto_turf.encode(msg, subject: "simple")
17
+ expect(encoded).to eq("\u0000\u0000\u0000\u0000\u000F\u0000" + msg.to_proto)
18
+
19
+ # if we do it again we should not see any more requests
20
+ encoded2 = proto_turf.encode(msg, subject: "simple")
21
+ expect(encoded2).to eq(encoded)
22
+
23
+ expect(stub).to have_been_requested.once
24
+ end
25
+
26
+ it "should encode a complex message" do
27
+ schema = File.read("#{__dir__}/schemas/referenced/referer.proto")
28
+ dep_schema = File.read("#{__dir__}/schemas/simple/simple.proto")
29
+ dep_stub = stub_request(:post, "http://localhost:8081/subjects/simple%2Fsimple.proto/versions")
30
+ .with(body: {"schemaType" => "PROTOBUF",
31
+ "references" => [],
32
+ "schema" => dep_schema}).to_return_json(body: {id: 15})
33
+ version_stub = stub_request(:get, "http://localhost:8081/schemas/ids/15/versions")
34
+ .to_return_json(body: [{version: 1, subject: "simple/simple.proto"}])
35
+ stub = stub_request(:post, "http://localhost:8081/subjects/referenced/versions")
36
+ .with(body: {"schemaType" => "PROTOBUF",
37
+ "references" => [
38
+ {
39
+ name: "simple/simple.proto",
40
+ subject: "simple/simple.proto",
41
+ version: 1
42
+ }
43
+ ],
44
+ "schema" => schema}).to_return_json(body: {id: 20})
45
+ msg = Referenced::V1::MessageB::MessageBA.new(
46
+ simple: Simple::V1::SimpleMessage.new(name: "my name")
47
+ )
48
+ encoded = proto_turf.encode(msg, subject: "referenced")
49
+ expect(encoded).to eq("\u0000\u0000\u0000\u0000\u0014\u0004\u0002\u0000" + msg.to_proto)
50
+
51
+ # if we do it again we should not see any more requests
52
+ encoded2 = proto_turf.encode(msg, subject: "referenced")
53
+ expect(encoded2).to eq(encoded)
54
+ expect(stub).to have_been_requested.once
55
+ expect(dep_stub).to have_been_requested.once
56
+ expect(version_stub).to have_been_requested.once
57
+ end
58
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: referenced/referer.proto
5
+
6
+ require "google/protobuf"
7
+
8
+ require "simple/simple_pb"
9
+
10
+ descriptor_data = "\n\x18referenced/referer.proto\x12\rreferenced.v1\x1a\x13simple/simple.proto\"j\n\x08MessageA\x1a\x43\n\tMessageAA\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06simple\x18\x02 \x01(\x0b\x32\x18.simple.v1.SimpleMessage\x1a\x19\n\tMessageAB\x12\x0c\n\x04name\x18\x01 \x01(\t\"j\n\x08MessageB\x1a\x43\n\tMessageBA\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06simple\x18\x02 \x01(\x0b\x32\x18.simple.v1.SimpleMessage\x1a\x19\n\tMessageBB\x12\x0c\n\x04name\x18\x01 \x01(\tb\x06proto3"
11
+
12
+ pool = Google::Protobuf::DescriptorPool.generated_pool
13
+ pool.add_serialized_file(descriptor_data)
14
+
15
+ module Referenced
16
+ module V1
17
+ MessageA = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("referenced.v1.MessageA").msgclass
18
+ MessageA::MessageAA = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("referenced.v1.MessageA.MessageAA").msgclass
19
+ MessageA::MessageAB = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("referenced.v1.MessageA.MessageAB").msgclass
20
+ MessageB = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("referenced.v1.MessageB").msgclass
21
+ MessageB::MessageBA = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("referenced.v1.MessageB.MessageBA").msgclass
22
+ MessageB::MessageBB = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("referenced.v1.MessageB.MessageBB").msgclass
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: simple/simple.proto
5
+
6
+ require "google/protobuf"
7
+
8
+ descriptor_data = "\n\x13simple/simple.proto\x12\tsimple.v1\"\x1d\n\rSimpleMessage\x12\x0c\n\x04name\x18\x01 \x01(\tb\x06proto3"
9
+
10
+ pool = Google::Protobuf::DescriptorPool.generated_pool
11
+ pool.add_serialized_file(descriptor_data)
12
+
13
+ module Simple
14
+ module V1
15
+ SimpleMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("simple.v1.SimpleMessage").msgclass
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ syntax = "proto3";
2
+
3
+ package referenced.v1;
4
+ import "simple/simple.proto";
5
+
6
+ message MessageA {
7
+ message MessageAA {
8
+ string name = 1;
9
+ simple.v1.SimpleMessage simple = 2;
10
+ }
11
+ message MessageAB {
12
+ string name = 1;
13
+ }
14
+ }
15
+
16
+ message MessageB {
17
+ message MessageBA {
18
+ string name = 1;
19
+ simple.v1.SimpleMessage simple = 2;
20
+ }
21
+ message MessageBB {
22
+ string name = 1;
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ syntax = "proto3";
2
+
3
+ package simple.v1;
4
+
5
+ message SimpleMessage {
6
+ string name = 1;
7
+ }
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
4
+ $LOAD_PATH.unshift(File.expand_path("gen", __dir__))
5
+ Dir["#{__dir__}/gen/**/*.rb"].each { |file| require file }
6
+ require "proto_turf"
7
+ require "webmock/rspec"
8
+
9
+ RSpec.configure do |config|
10
+ config.full_backtrace = true
11
+
12
+ config.shared_context_metadata_behavior = :apply_to_host_groups
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proto_turf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Orner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-14 00:00:00.000000000 Z
11
+ date: 2025-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: excon
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,34 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '3.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: standardrb
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
69
111
  description:
70
112
  email:
71
113
  - daniel.orner@flipp.com
@@ -73,7 +115,10 @@ executables: []
73
115
  extensions: []
74
116
  extra_rdoc_files: []
75
117
  files:
118
+ - ".rspec"
76
119
  - CHANGELOG.md
120
+ - Gemfile
121
+ - Gemfile.lock
77
122
  - LICENSE
78
123
  - README.md
79
124
  - lib/proto_turf.rb
@@ -81,6 +126,13 @@ files:
81
126
  - lib/proto_turf/confluent_schema_registry.rb
82
127
  - lib/proto_turf/version.rb
83
128
  - proto_turf.gemspec
129
+ - spec/decoding_spec.rb
130
+ - spec/encoding_spec.rb
131
+ - spec/gen/referenced/referer_pb.rb
132
+ - spec/gen/simple/simple_pb.rb
133
+ - spec/schemas/referenced/referer.proto
134
+ - spec/schemas/simple/simple.proto
135
+ - spec/spec_helper.rb
84
136
  homepage: https://github.com/flipp-oss/proto_turf
85
137
  licenses:
86
138
  - MIT