protobuf_transpiler 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55572283d38aaaf17ae92233d0a4e276f1f4fa969ecea798d85c838b46070605
4
- data.tar.gz: a1b7299db9e0ac59d5c818b729e5515400a9f0127f18bf99cb074685d8f7fb60
3
+ metadata.gz: '0872a221c991587b5b5dde741f68f412c30a38db4ffdef9b51629d058ba9c1f0'
4
+ data.tar.gz: 4fe978a2ea8180b0677048e8622540e95c7f78bdae6a18b7984be7d5ded5ec7d
5
5
  SHA512:
6
- metadata.gz: c157a107eada279ba863e049248cfb38a8d573cb11c97fe7a92b8cf9af245f04338433845021381b9e5d2c51d880621bc82bf32a8e371a59ca0f2d4b71b19ae8
7
- data.tar.gz: e9240d2f92d78141d79e993ca8fda889540a7fa14d7c72fd8556d25e35e6aebba092ac80cac9768a53989579b0d83f2f8241e9de0d7fb1a11b2b19801434b5e1
6
+ metadata.gz: 113d630819223b40ee24f319ee429aca18abc8e3f5a4b5a8ad9a685174dff6389940531f5a3f2157829e48646e8ea22589ffc8fdc6311f4c4092e1fdc17eb15a
7
+ data.tar.gz: 65cf4a6fdc76306138598464c5b04b24da511a5b0593d8143733039b93560e5fd04a7a182ffb1a01c56f4d2fb070817f4b0fee5fd4fd025e1d3a73a1a5f328f4
data/CHANGELOG.md CHANGED
@@ -8,6 +8,20 @@
8
8
  ### Bug fixes
9
9
  )-->
10
10
 
11
+ ## 1.1.1 2023-11-13
12
+ ### Bug fixes
13
+ - require google-protobuf where its monkey patch is made
14
+
15
+ ## 1.1.0 2023-08-21
16
+ ### New features
17
+ - Add annotation support for:
18
+ - streams
19
+ - oneofs
20
+ - maps
21
+ - nested messages
22
+ ### Bug fixes
23
+ - Annotate task now correctly replaces existing annotations
24
+
11
25
  ## 1.0.0 2023-07-24
12
26
 
13
27
  First release. Refer to [README.md](README.md) for the full documentation.
data/README.md CHANGED
@@ -37,12 +37,12 @@ Finally, following the stubs generation, the task also creates a ruby file for a
37
37
  For example if you have a gem defining proto files with this structure:
38
38
  ```
39
39
  public
40
- ├── mod1
41
- │ └── sample1.proto
42
- ├── mod2
43
- │ └── sample2.proto
40
+ ├── mod1
41
+ │ └── sample1.proto
42
+ ├── mod2
43
+ │ └── sample2.proto
44
44
  ```
45
- you will get the follwing structure nested in `app/stubs`
45
+ you will get the following structure nested in `app/stubs`:
46
46
  ```
47
47
  app/stubs
48
48
  ├── mod1
@@ -63,15 +63,26 @@ rake grpc_stubs:annotate
63
63
  ```
64
64
  As stated in [generate](#generate) this task is executed automatically unless you opt out after the generation step. Leveraging reflection, Messages and Services are inspected and a comment summary is prepended in the corresponding stub file.
65
65
 
66
+ The annotations of messages follow these conventions:
67
+ - each message is reported with its fully qualified name
68
+ - fields are indented in the lines following the message name and are reported as `name: type`
69
+ - `repeated` fields are annotated with their type enclosed in brackets (`[type]`)
70
+ - `map` fields are annotated with angular brackets: `Map<key_type, value_type>`
71
+ - `oneof` fields are annotated with their wrapper name, then each possible variant placed on a new line, further indented and prepended with `| `.
72
+
66
73
  Here's an example of annotations of some messages:
67
74
  ```
68
75
  # ===== Protobuf Annotation =====
69
76
  # Test::GetJobReq
70
77
  # id: uint64
78
+ # some_oneof_wrapper:
79
+ # | alternative: string
80
+ # | another: uint64
71
81
  # Test::GetJobResp
72
82
  # id: uint64
73
83
  # name: string
74
84
  # surname: string
85
+ # notes: [string]
75
86
  # ===== Protobuf Annotation =====
76
87
  ```
77
88
  and some rpcs:
@@ -84,6 +95,7 @@ and some rpcs:
84
95
  # ===== Protobuf Annotation =====
85
96
  ```
86
97
 
98
+
87
99
  ## Future extensions
88
100
  - Support nested messages definition
89
101
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProtobufTranspiler
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.1'
5
5
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "google/protobuf"
3
4
  require_relative "protobuf_transpiler/version"
4
5
 
5
6
  module ProtobufTranspiler
@@ -12,7 +13,7 @@ module ProtobufTranspiler
12
13
  proto_paths = proto_files
13
14
  .split.map { |p| p.sub %r{(?<=public).*}, '' }
14
15
  .uniq.join ' '
15
- out_path = "#{Rails.root}/app/stubs/"
16
+ out_path = "#{Rails.root}/app/stubs/"
16
17
  FileUtils.mkdir_p out_path
17
18
  `grpc_tools_ruby_protoc --ruby_out=#{out_path} --grpc_out=#{out_path} #{proto_files} -I #{proto_paths}`
18
19
 
@@ -20,7 +21,7 @@ module ProtobufTranspiler
20
21
  unless keep_require
21
22
  Dir['app/stubs/**/*.rb'].each do |fp|
22
23
  f = File.read fp
23
- File.write fp, (f.sub /\n(require.*?'\n)+/, '')
24
+ File.write fp, (f.sub %r{\n(require.*?'\n)+}, '')
24
25
  end
25
26
  end
26
27
 
@@ -30,7 +31,7 @@ module ProtobufTranspiler
30
31
  .each { |dir|
31
32
  requires = Dir.chdir dir do
32
33
  curr_dir = Dir.pwd.split('/').last
33
- Dir['*.rb'].map { |s| "require_relative './#{curr_dir}/#{s.sub(/.rb$/, '')}'" }
34
+ Dir['*.rb'].map { |s| "require_relative './#{curr_dir}/#{s.sub %r{.rb$}, ''}'" }
34
35
  end
35
36
  File.write "#{dir}.rb", requires.join("\n")
36
37
  }
@@ -52,6 +53,7 @@ module ProtobufTranspiler
52
53
  stubs_modules.each do |m|
53
54
  out = m
54
55
  .constants
56
+ .sort
55
57
  .map { |c| m.const_get c }
56
58
  .each_with_object({ messages: [], services: [] }) { |c, acc|
57
59
  if c.is_a? Class
@@ -60,7 +62,7 @@ module ProtobufTranspiler
60
62
  acc[:services] << module_annotations(c)
61
63
  end
62
64
  }
63
- types_file, services_file = Dir["app/stubs/#{m.name.downcase}/*.rb"]
65
+ types_file, services_file = Dir["app/stubs/#{m.name.underscore}/*.rb"]
64
66
  .sort_by { |s| s.scan('services').count }
65
67
  [types_file, services_file]
66
68
  .zip([out[:messages], out[:services]])
@@ -70,20 +72,64 @@ module ProtobufTranspiler
70
72
 
71
73
  private
72
74
 
73
- ANNOTATE_DELIMITER = '===== Protobuf Annotation ====='
75
+ ANNOTATE_DELIMITER = '# ===== Protobuf Annotation ====='
74
76
 
75
- def class_annotations c
76
- c
77
- .descriptor.entries.map { |d| "\t#{d.name}: #{d.type}" }
78
- .prepend("#{c.name}")
79
- .join "\n"
77
+ def class_annotations klass
78
+ oneof_fields, oneof_annotations = lambda do |descriptor|
79
+ [
80
+ descriptor.each_oneof
81
+ .flat_map { |o| o.entries.map(&:name) },
82
+ descriptor.each_oneof
83
+ .map { |o| ["#{o.name}:", o.entries.map { |e| "\t| #{e.name}: #{type_handler e}" }].join("\n") }
84
+ .map { |s| s.gsub(%r{\t}, "\t\t").prepend("\t") + "\n" }
85
+ ]
86
+ end.call(klass.descriptor)
87
+
88
+ map_fields = lambda do |descriptor, instance|
89
+ descriptor.entries
90
+ .map(&:name)
91
+ .filter { |n| instance[n].class == Google::Protobuf::Map }
92
+ end.call(klass.descriptor, klass.new)
93
+
94
+ [
95
+ klass.name.to_s,
96
+ klass.constants(false).sort
97
+ .map { |msg| klass.const_get msg }
98
+ .map { |msg_class| class_annotations(msg_class) }
99
+ .map { |s| s.gsub(%r{\t}, "\t\t").prepend("\t") }
100
+ .prepend("\n"),
101
+ oneof_annotations,
102
+ klass.descriptor.entries
103
+ .reject{|d|oneof_fields.include? d.name}
104
+ .map { |d|
105
+ "\t#{d.name}: "+
106
+ type_handler(d, map_fields)
107
+ }
108
+ .join("\n"),
109
+ "\n"
110
+
111
+ ].join('')
80
112
  end
81
113
 
82
- def module_annotations m
83
- m
114
+ def type_handler d, map_fields = []
115
+ case
116
+ when d.is_a?(Symbol)
117
+ d
118
+ when map_fields.include?(d.name)
119
+ d.subtype.entries.then { |k,v| "Map<#{k.type}, #{type_handler(v)}>" }
120
+ when d.type == :message
121
+ d.subtype.msgclass.then{|t| d.label == :repeated ? "[#{t}]" : t}
122
+ else
123
+ d.type.then{|t| d.label == :repeated ? "[#{t}]" : t}
124
+ end.to_s
125
+ end
126
+
127
+ def module_annotations mod
128
+ mod
84
129
  .const_get('Service')
85
- .rpc_descs.map { |_, d| "\t#{d.name}(#{d.input}): #{d.output}" }
86
- .prepend("#{m.name}")
130
+ .rpc_descs.sort
131
+ .map { |_, d| "\t#{d.name}(#{d.input}): #{d.output}" }
132
+ .prepend(mod.name.to_s)
87
133
  .join "\n"
88
134
  end
89
135
 
@@ -92,13 +138,33 @@ module ProtobufTranspiler
92
138
  content = content.join("\n").gsub(%r{^}, '# ')
93
139
  new_content = if old_content.match? ANNOTATE_DELIMITER
94
140
  # replace annotation content
95
- old_content.sub %r{(?<=#{ANNOTATE_DELIMITER})(.|\n)*?(?=##{ANNOTATE_DELIMITER})}, "\n#{content}\n"
141
+ old_content.sub %r{(?<=#{ANNOTATE_DELIMITER}\n)(.|\n)*?(?=\n#{ANNOTATE_DELIMITER})}, "\n#{content}"
96
142
  else
97
143
  # find first spot after comments
98
144
  # add and fill annotation
99
- old_content.sub %r{^[^#]}, "\n# #{ANNOTATE_DELIMITER}\n#{content}\n# #{ANNOTATE_DELIMITER}\n\n"
145
+ old_content.sub %r{^[^#]}, "\n#{ANNOTATE_DELIMITER}\n\n#{content}\n#{ANNOTATE_DELIMITER}\n\n"
100
146
  end
101
147
  File.write file, new_content
102
148
  end
103
149
  end
104
150
  end
151
+
152
+ class GRPC::RpcDesc::Stream
153
+
154
+ def to_s
155
+ "stream #{type}"
156
+ end
157
+ end
158
+
159
+ monkey_patch_descriptor = Module.new do
160
+ def each_oneof(&)
161
+ return super if block_given?
162
+
163
+ Enumerator.new do |y|
164
+ super do |d|
165
+ y << d
166
+ end
167
+ end
168
+ end
169
+ end
170
+ Google::Protobuf::Descriptor.prepend monkey_patch_descriptor
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobuf_transpiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moku S.r.l.
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-07-24 00:00:00.000000000 Z
12
+ date: 2023-11-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-protobuf