schema_registry_client 0.0.7 → 0.0.8
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -30
- data/LICENSE +2 -0
- data/README.md +51 -6
- data/Rakefile +1 -1
- data/lib/schema_registry_client/avro_schema_store.rb +8 -8
- data/lib/schema_registry_client/cached_confluent_schema_registry.rb +5 -5
- data/lib/schema_registry_client/confluent_schema_registry.rb +12 -12
- data/lib/schema_registry_client/output/json_schema.rb +12 -12
- data/lib/schema_registry_client/output/proto_text.rb +45 -45
- data/lib/schema_registry_client/schema/avro.rb +44 -40
- data/lib/schema_registry_client/schema/base.rb +27 -29
- data/lib/schema_registry_client/schema/proto_json_schema.rb +15 -17
- data/lib/schema_registry_client/schema/protobuf.rb +101 -101
- data/lib/schema_registry_client/version.rb +1 -1
- data/lib/schema_registry_client.rb +20 -22
- data/schema_registry_client.gemspec +20 -20
- data/spec/decoding_spec.rb +53 -53
- data/spec/encoding_spec.rb +90 -90
- data/spec/json_schema_spec.rb +2 -2
- data/spec/proto_text_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -5
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c4fb0ad39418dd0eb14e803f4c0652e47e64950b8684f564221a95b024177c1
|
|
4
|
+
data.tar.gz: c04a0a44298ff123a0a63cf530fe2c2ae56b7230cc740e2d02577f712d045e41
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c68cf8a284acdaad830acbbc76ea49b2cb1431b69e3c2961218f5c8af399b89d64f8b5eb1e25536e415f5720080152853f885d9984b47790ffd02d01cad73709
|
|
7
|
+
data.tar.gz: 7fb3f61b7159bf9f461f3fc9b6f8d0f145592f18a35b1e02d284a6f2ed62c95d30a6d8ff1082b2607976f134e6a74e1416e00483e61f8db2ecf27f601112bd84
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## UNRELEASED
|
|
9
9
|
|
|
10
|
+
# 0.0.8 - 2026-02-04
|
|
11
|
+
|
|
12
|
+
* Support passing a `schema_store` into the `Avro` schema backend.
|
|
13
|
+
* Move schema backend methods from class-level to instance-level and require instantiation.
|
|
14
|
+
|
|
10
15
|
# 0.0.7 - 2026-01-05
|
|
11
16
|
|
|
12
17
|
* Switch to using `SchemaRegistry::Client` instead of bare `SchemaRegistry`.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
schema_registry_client (0.0.
|
|
4
|
+
schema_registry_client (0.0.8)
|
|
5
5
|
avro
|
|
6
6
|
excon
|
|
7
7
|
google-protobuf
|
|
@@ -22,33 +22,12 @@ GEM
|
|
|
22
22
|
docile (1.4.1)
|
|
23
23
|
excon (1.3.2)
|
|
24
24
|
logger
|
|
25
|
-
google-protobuf (4.33.2)
|
|
26
|
-
bigdecimal
|
|
27
|
-
rake (>= 13)
|
|
28
|
-
google-protobuf (4.33.2-aarch64-linux-gnu)
|
|
29
|
-
bigdecimal
|
|
30
|
-
rake (>= 13)
|
|
31
|
-
google-protobuf (4.33.2-aarch64-linux-musl)
|
|
32
|
-
bigdecimal
|
|
33
|
-
rake (>= 13)
|
|
34
25
|
google-protobuf (4.33.2-arm64-darwin)
|
|
35
26
|
bigdecimal
|
|
36
27
|
rake (>= 13)
|
|
37
|
-
google-protobuf (4.33.2-x86-linux-gnu)
|
|
38
|
-
bigdecimal
|
|
39
|
-
rake (>= 13)
|
|
40
|
-
google-protobuf (4.33.2-x86-linux-musl)
|
|
41
|
-
bigdecimal
|
|
42
|
-
rake (>= 13)
|
|
43
|
-
google-protobuf (4.33.2-x86_64-darwin)
|
|
44
|
-
bigdecimal
|
|
45
|
-
rake (>= 13)
|
|
46
28
|
google-protobuf (4.33.2-x86_64-linux-gnu)
|
|
47
29
|
bigdecimal
|
|
48
30
|
rake (>= 13)
|
|
49
|
-
google-protobuf (4.33.2-x86_64-linux-musl)
|
|
50
|
-
bigdecimal
|
|
51
|
-
rake (>= 13)
|
|
52
31
|
hashdiff (1.2.1)
|
|
53
32
|
json (2.18.0)
|
|
54
33
|
language_server-protocol (3.17.0.5)
|
|
@@ -127,15 +106,8 @@ GEM
|
|
|
127
106
|
hashdiff (>= 0.4.0, < 2.0.0)
|
|
128
107
|
|
|
129
108
|
PLATFORMS
|
|
130
|
-
aarch64-linux-gnu
|
|
131
|
-
aarch64-linux-musl
|
|
132
109
|
arm64-darwin
|
|
133
|
-
|
|
134
|
-
x86-linux-gnu
|
|
135
|
-
x86-linux-musl
|
|
136
|
-
x86_64-darwin
|
|
137
|
-
x86_64-linux-gnu
|
|
138
|
-
x86_64-linux-musl
|
|
110
|
+
x86_64-linux
|
|
139
111
|
|
|
140
112
|
DEPENDENCIES
|
|
141
113
|
bundler (~> 2.0)
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# schema_registry_client
|
|
2
2
|
|
|
3
|
-
`schema_registry_client` is a library to interact with the Confluent Schema Registry
|
|
3
|
+
`schema_registry_client` is a library to interact with the Confluent Schema Registry. It is inspired by and based off of [avro_turf](https://github.com/dasch/avro_turf).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -24,21 +24,66 @@ SchemaRegistry interacts with the Confluent Schema Registry, and caches all resu
|
|
|
24
24
|
|
|
25
25
|
Example usage:
|
|
26
26
|
|
|
27
|
+
### Avro
|
|
28
|
+
|
|
29
|
+
Note that unlike AvroTurf, you must concatenate the namespace and schema name together when encoding.
|
|
30
|
+
|
|
27
31
|
```ruby
|
|
28
32
|
require 'schema_registry_client'
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
client = SchemaRegistry::Client.new(registry_url: 'http://localhost:8081', schema_type: SchemaRegistry::Schema::Avro.new)
|
|
35
|
+
SchemaRegistry.avro_schema_path = 'path/to/schemas'
|
|
36
|
+
message = {field1: 'value1', field2: 42 }
|
|
37
|
+
encoded = client.encode(message, schema_name: 'com.my-namespace.MySchema', subject: 'my-subject')
|
|
38
|
+
|
|
39
|
+
# Decoding
|
|
40
|
+
|
|
41
|
+
decoded_avro_message = client.decode(encoded_string)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Protobuf
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
client = SchemaRegistry::Client.new(registry_url: 'http://localhost:8081', schema_type: SchemaRegistry::Schema::Protobuf.new)
|
|
48
|
+
message = MyProtoMessage.new(field1: 'value1', field2: 42)
|
|
49
|
+
encoded = client.encode(message, subject: 'my-proto-subject')
|
|
33
50
|
|
|
34
51
|
# Decoding
|
|
52
|
+
decoded_proto_message = client.decode(encoded_string)
|
|
53
|
+
```
|
|
35
54
|
|
|
36
|
-
|
|
55
|
+
### Protobuf JSON Schema
|
|
56
|
+
|
|
57
|
+
Since Protobuf is [not recommended to use for Kafka keys](https://protobuf.dev/programming-guides/encoding/#implications), it's instead recommended that you use the `ProtoJsonSchema` format. This will transform the Protobuf message into a JSON schema and register that with the registry instead. The encoded message will be the JSON representation of the Protobuf message, with keys sorted alphabetically to ensure consistent encoding.
|
|
58
|
+
|
|
59
|
+
Note that the algorithm to translate into JSON Schema is currently very naive (e.g. it does not handle nested messages) since keys should usually be very simple. If more complex logic is needed, pull requests are welcome.
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
client = SchemaRegistry::Client.new(registry_url: 'http://localhost:8081', schema_type: SchemaRegistry::Schema::ProtoJsonSchema)
|
|
63
|
+
message = MyProtoMessage.new(field1: 'value1', field2: 42)
|
|
64
|
+
encoded = client.encode(message, subject: 'my-proto-subject') # will register a JSON Schema subject and encode into JSON
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
You can use JSON Schema with regular Ruby hashes as well by passing `schema_text` into the encode method:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
client = SchemaRegistry::Client.new(registry_url: 'http://localhost:8081', schema_type: SchemaRegistry::Schema::ProtoJsonSchema)
|
|
72
|
+
message = { field1: 'value1', field2: 42 }
|
|
73
|
+
schema_text = {
|
|
74
|
+
"type" => "object",
|
|
75
|
+
"properties" => {
|
|
76
|
+
"field1" => { "type" => "string" },
|
|
77
|
+
"field2" => { "type" => "integer" }
|
|
78
|
+
},
|
|
79
|
+
"required" => ["field1", "field2"]
|
|
80
|
+
}.to_json
|
|
81
|
+
encoded = client.encode(message, subject: 'my-proto-subject', schema_text: schema_text)
|
|
37
82
|
```
|
|
38
83
|
|
|
39
84
|
## Notes about usage
|
|
40
85
|
|
|
41
|
-
* When decoding, this library does *not* attempt to fully parse the
|
|
86
|
+
* When decoding, this library does *not* attempt to fully parse the Protobuf 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.
|
|
42
87
|
|
|
43
88
|
### Regenerating test protos
|
|
44
89
|
Run the following to regenerate:
|
data/Rakefile
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'avro'
|
|
4
4
|
|
|
5
5
|
module SchemaRegistry
|
|
6
6
|
class AvroSchemaStore
|
|
7
7
|
def initialize(path: nil)
|
|
8
|
-
@path = path or raise
|
|
8
|
+
@path = path or raise 'Please specify a schema path'
|
|
9
9
|
@schemas = {}
|
|
10
10
|
@schema_text = {}
|
|
11
11
|
@mutex = Mutex.new
|
|
@@ -38,14 +38,14 @@ module SchemaRegistry
|
|
|
38
38
|
|
|
39
39
|
# Loads all schema definition files in the `schemas_dir`.
|
|
40
40
|
def load_schemas!
|
|
41
|
-
pattern = [@path,
|
|
41
|
+
pattern = [@path, '**', '*.avsc'].join('/')
|
|
42
42
|
|
|
43
43
|
Dir.glob(pattern) do |schema_path|
|
|
44
44
|
# Remove the path prefix.
|
|
45
|
-
schema_path.sub!(%r{^/?#{@path}/},
|
|
45
|
+
schema_path.sub!(%r{^/?#{@path}/}, '')
|
|
46
46
|
|
|
47
47
|
# Replace `/` with `.` and chop off the file extension.
|
|
48
|
-
schema_name = File.basename(schema_path.tr(
|
|
48
|
+
schema_name = File.basename(schema_path.tr('/', '.'), '.avsc')
|
|
49
49
|
|
|
50
50
|
# Load and cache the schema.
|
|
51
51
|
find(schema_name)
|
|
@@ -54,8 +54,8 @@ module SchemaRegistry
|
|
|
54
54
|
|
|
55
55
|
# @param schema_hash [Hash]
|
|
56
56
|
def add_schema(schema_hash)
|
|
57
|
-
name = schema_hash[
|
|
58
|
-
namespace = schema_hash[
|
|
57
|
+
name = schema_hash['name']
|
|
58
|
+
namespace = schema_hash['namespace']
|
|
59
59
|
full_name = Avro::Name.make_fullname(name, namespace)
|
|
60
60
|
return if @schemas.key?(full_name)
|
|
61
61
|
|
|
@@ -120,7 +120,7 @@ module SchemaRegistry
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
def build_schema_path(fullname)
|
|
123
|
-
*namespace, schema_name = fullname.split(
|
|
123
|
+
*namespace, schema_name = fullname.split('.')
|
|
124
124
|
File.join(@path, *namespace, "#{schema_name}.avsc")
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -31,7 +31,7 @@ module SchemaRegistry
|
|
|
31
31
|
return @versions_by_subject_and_id[key] if @versions_by_subject_and_id[key]
|
|
32
32
|
|
|
33
33
|
results = @upstream.schema_subject_versions(id)
|
|
34
|
-
@versions_by_subject_and_id[key] = results&.find { |r| r[
|
|
34
|
+
@versions_by_subject_and_id[key] = results&.find { |r| r['subject'] == subject }&.dig('version')
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# @param subject [String] the subject to check
|
|
@@ -45,13 +45,13 @@ module SchemaRegistry
|
|
|
45
45
|
# @param schema [String] the schema text to register
|
|
46
46
|
# @param references [Array<Hash>] optional references to other schemas
|
|
47
47
|
# @param schema_type [String]
|
|
48
|
-
def register(subject, schema, references: [], schema_type:
|
|
48
|
+
def register(subject, schema, references: [], schema_type: 'PROTOBUF')
|
|
49
49
|
key = [subject, schema]
|
|
50
50
|
|
|
51
51
|
@ids_by_schema[key] ||= @upstream.register(subject,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
schema,
|
|
53
|
+
references: references,
|
|
54
|
+
schema_type: schema_type)
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'excon'
|
|
4
4
|
|
|
5
5
|
module SchemaRegistry
|
|
6
6
|
class ConfluentSchemaRegistry
|
|
7
|
-
CONTENT_TYPE =
|
|
7
|
+
CONTENT_TYPE = 'application/vnd.schemaregistry.v1+json'
|
|
8
8
|
|
|
9
9
|
def initialize( # rubocop:disable Metrics/ParameterLists
|
|
10
10
|
url,
|
|
@@ -25,11 +25,11 @@ module SchemaRegistry
|
|
|
25
25
|
retry_limit: nil
|
|
26
26
|
)
|
|
27
27
|
@path_prefix = path_prefix
|
|
28
|
-
@schema_context_prefix = schema_context.nil? ?
|
|
29
|
-
@schema_context_options = schema_context.nil? ? {} : {query: {subject: @schema_context_prefix}}
|
|
28
|
+
@schema_context_prefix = schema_context.nil? ? '' : ":.#{schema_context}:"
|
|
29
|
+
@schema_context_options = schema_context.nil? ? {} : { query: { subject: @schema_context_prefix } }
|
|
30
30
|
@logger = logger
|
|
31
31
|
headers = Excon.defaults[:headers].merge(
|
|
32
|
-
|
|
32
|
+
'Content-Type' => CONTENT_TYPE
|
|
33
33
|
)
|
|
34
34
|
params = {
|
|
35
35
|
headers: headers,
|
|
@@ -59,7 +59,7 @@ module SchemaRegistry
|
|
|
59
59
|
def fetch(id)
|
|
60
60
|
@logger.info "Fetching schema with id #{id}"
|
|
61
61
|
data = get("/schemas/ids/#{id}", idempotent: true, **@schema_context_options)
|
|
62
|
-
data.fetch(
|
|
62
|
+
data.fetch('schema')
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# @param schema_id [Integer] the schema ID to fetch versions for
|
|
@@ -72,13 +72,13 @@ module SchemaRegistry
|
|
|
72
72
|
# @param schema [String] the schema text to check
|
|
73
73
|
# @param references [Array<Hash>] optional references to other schemas
|
|
74
74
|
# @return [Integer] the ID of the registered schema
|
|
75
|
-
def register(subject, schema, references: [], schema_type:
|
|
75
|
+
def register(subject, schema, references: [], schema_type: 'PROTOBUF')
|
|
76
76
|
data = post("/subjects/#{@schema_context_prefix}#{CGI.escapeURIComponent(subject)}/versions",
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
body: { schemaType: schema_type,
|
|
78
|
+
references: references,
|
|
79
|
+
schema: schema.to_s }.to_json)
|
|
80
80
|
|
|
81
|
-
id = data.fetch(
|
|
81
|
+
id = data.fetch('id')
|
|
82
82
|
|
|
83
83
|
@logger.info "Registered schema for subject `#{@schema_context_prefix}#{subject}`; id = #{id}"
|
|
84
84
|
|
|
@@ -106,7 +106,7 @@ module SchemaRegistry
|
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def request(path, **options)
|
|
109
|
-
options = {expects: 200}.merge!(options)
|
|
109
|
+
options = { expects: 200 }.merge!(options)
|
|
110
110
|
path = File.join(@path_prefix, path) unless @path_prefix.nil?
|
|
111
111
|
response = @connection.request(path: path, **options)
|
|
112
112
|
JSON.parse(response.body)
|
|
@@ -5,20 +5,20 @@ module SchemaRegistry
|
|
|
5
5
|
module JsonSchema
|
|
6
6
|
class << self
|
|
7
7
|
def fetch(message_name)
|
|
8
|
-
name = message_name.start_with?(
|
|
8
|
+
name = message_name.start_with?('.') ? message_name[1..] : message_name
|
|
9
9
|
Google::Protobuf::DescriptorPool.generated_pool.lookup(name)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def output(descriptor, path: nil)
|
|
13
13
|
properties = {}
|
|
14
14
|
result = {
|
|
15
|
-
"$schema":
|
|
16
|
-
type:
|
|
15
|
+
"$schema": 'https://json-schema.org/draft/2020-12/schema',
|
|
16
|
+
type: 'object',
|
|
17
17
|
properties: properties
|
|
18
18
|
}
|
|
19
19
|
if path
|
|
20
20
|
# follow path down
|
|
21
|
-
parts = path.split(
|
|
21
|
+
parts = path.split('.')
|
|
22
22
|
field_name = parts.last
|
|
23
23
|
parts[...-1].each do |part|
|
|
24
24
|
field = descriptor.field.find { |f| f.name == part }
|
|
@@ -42,12 +42,12 @@ module SchemaRegistry
|
|
|
42
42
|
if field.label == :LABEL_REPEATED && !ignore_repeated
|
|
43
43
|
if klass&.options.respond_to?(:map_entry) && klass.options.map_entry
|
|
44
44
|
return {
|
|
45
|
-
type:
|
|
45
|
+
type: 'object',
|
|
46
46
|
additionalProperties: field_object(klass.field[1])
|
|
47
47
|
}
|
|
48
48
|
end
|
|
49
49
|
return {
|
|
50
|
-
type:
|
|
50
|
+
type: 'array',
|
|
51
51
|
items: field_object(field, ignore_repeated: true)
|
|
52
52
|
}
|
|
53
53
|
end
|
|
@@ -57,18 +57,18 @@ module SchemaRegistry
|
|
|
57
57
|
def field_type(field, klass)
|
|
58
58
|
case field.type
|
|
59
59
|
when :TYPE_INT32, :TYPE_UINT32, :TYPE_SINT32, :TYPE_FIXED32, :TYPE_SFIXED32
|
|
60
|
-
{type:
|
|
60
|
+
{ type: 'integer' }
|
|
61
61
|
when :TYPE_FLOAT, :TYPE_DOUBLE
|
|
62
|
-
{type:
|
|
62
|
+
{ type: 'number' }
|
|
63
63
|
when :TYPE_INT64, :TYPE_UINT64, :TYPE_SINT64, :TYPE_FIXED64, :TYPE_SFIXED64, :TYPE_STRING, :TYPE_BYTES
|
|
64
|
-
{type:
|
|
64
|
+
{ type: 'string' }
|
|
65
65
|
when :TYPE_BOOL
|
|
66
|
-
{type:
|
|
66
|
+
{ type: 'boolean' }
|
|
67
67
|
else
|
|
68
68
|
if klass.is_a?(Google::Protobuf::EnumDescriptorProto)
|
|
69
|
-
{enum: klass.to_h[:value].map { |h| h[:name] }}
|
|
69
|
+
{ enum: klass.to_h[:value].map { |h| h[:name] } }
|
|
70
70
|
else
|
|
71
|
-
{type:
|
|
71
|
+
{ type: 'object' }
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
end
|
|
@@ -18,7 +18,7 @@ module SchemaRegistry
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def write_indent(str)
|
|
21
|
-
@indent.times { write(
|
|
21
|
+
@indent.times { write(' ') }
|
|
22
22
|
write(str)
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -42,7 +42,7 @@ module SchemaRegistry
|
|
|
42
42
|
|
|
43
43
|
class << self
|
|
44
44
|
def fetch(message_name)
|
|
45
|
-
name = message_name.start_with?(
|
|
45
|
+
name = message_name.start_with?('.') ? message_name[1..] : message_name
|
|
46
46
|
Google::Protobuf::DescriptorPool.generated_pool.lookup(name)
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -87,23 +87,23 @@ module SchemaRegistry
|
|
|
87
87
|
info.indent
|
|
88
88
|
write_field(info, extension)
|
|
89
89
|
info.dedent
|
|
90
|
-
info.write_line(
|
|
90
|
+
info.write_line('}')
|
|
91
91
|
end
|
|
92
92
|
descriptor.extension.any?
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def write_reserved(writer, descriptor)
|
|
96
96
|
reserved = descriptor.reserved_range.map do |range|
|
|
97
|
-
|
|
97
|
+
range.start == range.end - 1 ? range.start.to_s : "#{range.start} to #{range.end - 1}"
|
|
98
98
|
end
|
|
99
99
|
found = false
|
|
100
100
|
if reserved.any?
|
|
101
101
|
found = true
|
|
102
|
-
writer.write_line("reserved #{reserved.join(
|
|
102
|
+
writer.write_line("reserved #{reserved.join(', ')};")
|
|
103
103
|
end
|
|
104
104
|
if descriptor.reserved_name.any?
|
|
105
105
|
found = true
|
|
106
|
-
writer.write_line("reserved #{descriptor.reserved_name.map(&:to_json).join(
|
|
106
|
+
writer.write_line("reserved #{descriptor.reserved_name.map(&:to_json).join(', ')};")
|
|
107
107
|
end
|
|
108
108
|
writer.writenl if found
|
|
109
109
|
end
|
|
@@ -124,7 +124,7 @@ module SchemaRegistry
|
|
|
124
124
|
|
|
125
125
|
def write_message(info, message_type)
|
|
126
126
|
info.message = message_type
|
|
127
|
-
info.write_indent(
|
|
127
|
+
info.write_indent('message ')
|
|
128
128
|
info.write("#{message_type.name} {")
|
|
129
129
|
info.writenl
|
|
130
130
|
info.indent
|
|
@@ -150,61 +150,61 @@ module SchemaRegistry
|
|
|
150
150
|
write_message(info, subtype)
|
|
151
151
|
end
|
|
152
152
|
info.dedent
|
|
153
|
-
info.write_line(
|
|
153
|
+
info.write_line('}')
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
def field_type(info, field_type)
|
|
157
157
|
case field_type.type
|
|
158
158
|
when :TYPE_INT32
|
|
159
|
-
|
|
159
|
+
'int32'
|
|
160
160
|
when :TYPE_INT64
|
|
161
|
-
|
|
161
|
+
'int64'
|
|
162
162
|
when :TYPE_UINT32
|
|
163
|
-
|
|
163
|
+
'uint32'
|
|
164
164
|
when :TYPE_UINT64
|
|
165
|
-
|
|
165
|
+
'uint64'
|
|
166
166
|
when :TYPE_SINT32
|
|
167
|
-
|
|
167
|
+
'sint32'
|
|
168
168
|
when :TYPE_SINT64
|
|
169
|
-
|
|
169
|
+
'sint64'
|
|
170
170
|
when :TYPE_FIXED32
|
|
171
|
-
|
|
171
|
+
'fixed32'
|
|
172
172
|
when :TYPE_FIXED64
|
|
173
|
-
|
|
173
|
+
'fixed64'
|
|
174
174
|
when :TYPE_SFIXED32
|
|
175
|
-
|
|
175
|
+
'sfixed32'
|
|
176
176
|
when :TYPE_SFIXED64
|
|
177
|
-
|
|
177
|
+
'sfixed64'
|
|
178
178
|
when :TYPE_FLOAT
|
|
179
|
-
|
|
179
|
+
'float'
|
|
180
180
|
when :TYPE_DOUBLE
|
|
181
|
-
|
|
181
|
+
'double'
|
|
182
182
|
when :TYPE_BOOL
|
|
183
|
-
|
|
183
|
+
'bool'
|
|
184
184
|
when :TYPE_STRING
|
|
185
|
-
|
|
185
|
+
'string'
|
|
186
186
|
when :TYPE_BYTES
|
|
187
|
-
|
|
187
|
+
'bytes'
|
|
188
188
|
when :TYPE_ENUM, :TYPE_MESSAGE
|
|
189
189
|
# remove leading .
|
|
190
190
|
type = fetch(field_type.type_name[1..])
|
|
191
|
-
name = type.name.sub("#{info.package}.#{info.message.name}.",
|
|
192
|
-
name.sub("#{info.package}.",
|
|
191
|
+
name = type.name.sub("#{info.package}.#{info.message.name}.", '')
|
|
192
|
+
name.sub("#{info.package}.", '')
|
|
193
193
|
end
|
|
194
194
|
end
|
|
195
195
|
|
|
196
196
|
def write_field(info, field, oneof: false)
|
|
197
197
|
return if !oneof && field.has_oneof_index?
|
|
198
198
|
|
|
199
|
-
info.write_indent(
|
|
199
|
+
info.write_indent('')
|
|
200
200
|
|
|
201
201
|
klass = nil
|
|
202
|
-
klass = fetch(field.type_name).to_proto if field.type_name && field.type_name !=
|
|
202
|
+
klass = fetch(field.type_name).to_proto if field.type_name && field.type_name != ''
|
|
203
203
|
|
|
204
204
|
if field.proto3_optional
|
|
205
|
-
info.write(
|
|
205
|
+
info.write('optional ')
|
|
206
206
|
elsif field.label == :LABEL_REPEATED && !klass&.options&.map_entry
|
|
207
|
-
info.write(
|
|
207
|
+
info.write('repeated ')
|
|
208
208
|
end
|
|
209
209
|
|
|
210
210
|
if klass&.options&.map_entry
|
|
@@ -215,24 +215,24 @@ module SchemaRegistry
|
|
|
215
215
|
info.write(" #{field.name} = #{field.number}")
|
|
216
216
|
|
|
217
217
|
write_field_options(info, field)
|
|
218
|
-
info.write(
|
|
218
|
+
info.write(';')
|
|
219
219
|
info.writenl
|
|
220
220
|
end
|
|
221
221
|
|
|
222
222
|
def write_field_options(info, field)
|
|
223
223
|
return unless field.options
|
|
224
224
|
|
|
225
|
-
info.write(
|
|
226
|
-
info.write(field.options.to_h.map { |name, value| "#{name} = #{value}" }.join(
|
|
225
|
+
info.write(' [')
|
|
226
|
+
info.write(field.options.to_h.map { |name, value| "#{name} = #{value}" }.join(', '))
|
|
227
227
|
write_options(info, field, include_option_label: false)
|
|
228
|
-
info.write(
|
|
228
|
+
info.write(']')
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
def write_oneofs(info, message)
|
|
232
232
|
message.oneof_decl.each_with_index do |oneof, i|
|
|
233
233
|
# synthetic oneof for proto3 optional fields
|
|
234
|
-
next if oneof.name.start_with?(
|
|
235
|
-
|
|
234
|
+
next if oneof.name.start_with?('_') &&
|
|
235
|
+
message.field.any? { |f| f.proto3_optional && f.name == oneof.name[1..] }
|
|
236
236
|
|
|
237
237
|
info.write_line("oneof #{oneof.name} {")
|
|
238
238
|
info.indent
|
|
@@ -240,12 +240,12 @@ module SchemaRegistry
|
|
|
240
240
|
write_field(info, field, oneof: true)
|
|
241
241
|
end
|
|
242
242
|
info.dedent
|
|
243
|
-
info.write_line(
|
|
243
|
+
info.write_line('}')
|
|
244
244
|
end
|
|
245
245
|
end
|
|
246
246
|
|
|
247
247
|
def write_enum(info, enum_type)
|
|
248
|
-
info.write(
|
|
248
|
+
info.write('enum ')
|
|
249
249
|
info.write("#{enum_type.name} {")
|
|
250
250
|
info.writenl
|
|
251
251
|
info.indent
|
|
@@ -254,30 +254,30 @@ module SchemaRegistry
|
|
|
254
254
|
info.write_line("#{value.name} = #{value.number};")
|
|
255
255
|
end
|
|
256
256
|
info.dedent
|
|
257
|
-
info.write_line(
|
|
257
|
+
info.write_line('}')
|
|
258
258
|
info.writenl
|
|
259
259
|
end
|
|
260
260
|
|
|
261
261
|
def method_type(package, name)
|
|
262
|
-
output = name.sub("#{package}.",
|
|
263
|
-
output = output[1..] if output.start_with?(
|
|
262
|
+
output = name.sub("#{package}.", '')
|
|
263
|
+
output = output[1..] if output.start_with?('.')
|
|
264
264
|
output
|
|
265
265
|
end
|
|
266
266
|
|
|
267
267
|
def write_service(info, service)
|
|
268
268
|
info.write_line("service #{service.name} {")
|
|
269
269
|
info.indent
|
|
270
|
-
service[
|
|
270
|
+
service['method'].each do |method|
|
|
271
271
|
info.write_indent("rpc #{method.name}(#{method_type(info.package, method.input_type)}) ")
|
|
272
272
|
info.write("returns (#{method_type(info.package, method.output_type)}) {")
|
|
273
273
|
info.writenl
|
|
274
274
|
info.indent
|
|
275
275
|
write_options(info, method) if method.options
|
|
276
276
|
info.dedent
|
|
277
|
-
info.write_line(
|
|
277
|
+
info.write_line('};')
|
|
278
278
|
end
|
|
279
279
|
info.dedent
|
|
280
|
-
info.write_line(
|
|
280
|
+
info.write_line('}')
|
|
281
281
|
end
|
|
282
282
|
|
|
283
283
|
# @return [Boolean] true if any options were written
|
|
@@ -289,7 +289,7 @@ module SchemaRegistry
|
|
|
289
289
|
|
|
290
290
|
found = false
|
|
291
291
|
json.each_key do |name|
|
|
292
|
-
option_name = name.tr(
|
|
292
|
+
option_name = name.tr('[]', '')
|
|
293
293
|
ext = fetch(option_name)
|
|
294
294
|
next if ext.nil?
|
|
295
295
|
|
|
@@ -306,7 +306,7 @@ module SchemaRegistry
|
|
|
306
306
|
info.write_indent(line)
|
|
307
307
|
info.writenl if i < lines.length - 1
|
|
308
308
|
end
|
|
309
|
-
info.write(
|
|
309
|
+
info.write(';')
|
|
310
310
|
else
|
|
311
311
|
info.write(options.to_json)
|
|
312
312
|
end
|