protobuf_transpiler 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 55572283d38aaaf17ae92233d0a4e276f1f4fa969ecea798d85c838b46070605
4
+ data.tar.gz: a1b7299db9e0ac59d5c818b729e5515400a9f0127f18bf99cb074685d8f7fb60
5
+ SHA512:
6
+ metadata.gz: c157a107eada279ba863e049248cfb38a8d573cb11c97fe7a92b8cf9af245f04338433845021381b9e5d2c51d880621bc82bf32a8e371a59ca0f2d4b71b19ae8
7
+ data.tar.gz: e9240d2f92d78141d79e993ca8fda889540a7fa14d7c72fd8556d25e35e6aebba092ac80cac9768a53989579b0d83f2f8241e9de0d7fb1a11b2b19801434b5e1
data/.rubocop.yml ADDED
@@ -0,0 +1,452 @@
1
+ AllCops:
2
+ TargetRubyVersion: '3.2'
3
+ Exclude:
4
+ - 'bin/**'
5
+
6
+ Gemspec/DeprecatedAttributeAssignment:
7
+ Enabled: true
8
+
9
+ Gemspec/DevelopmentDependencies:
10
+ Enabled: true
11
+
12
+ Gemspec/RequireMFA:
13
+ Enabled: false
14
+
15
+ Layout/AccessModifierIndentation:
16
+ EnforcedStyle: outdent
17
+
18
+ Layout/BeginEndAlignment:
19
+ EnforcedStyleAlignWith: begin
20
+
21
+ Layout/BlockAlignment:
22
+ EnforcedStyleAlignWith: start_of_block
23
+
24
+ Layout/CommentIndentation:
25
+ AllowForAlignment: true
26
+
27
+ Layout/EmptyLineAfterMultilineCondition:
28
+ Enabled: true
29
+
30
+ Layout/EndOfLine:
31
+ EnforcedStyle: lf
32
+
33
+ Layout/ExtraSpacing:
34
+ AllowForAlignment: true
35
+ AllowBeforeTrailingComments: true
36
+
37
+ Layout/HashAlignment:
38
+ EnforcedHashRocketStyle: table
39
+ EnforcedColonStyle: table
40
+ EnforcedLastArgumentHashStyle: ignore_implicit
41
+
42
+ Layout/LineContinuationLeadingSpace:
43
+ Enabled: true
44
+
45
+ Layout/LineContinuationSpacing:
46
+ Enabled: true
47
+
48
+ Layout/LineEndStringConcatenationIndentation:
49
+ Enabled: true
50
+
51
+ Layout/MultilineArrayLineBreaks:
52
+ Enabled: true
53
+
54
+ Layout/MultilineAssignmentLayout:
55
+ Enabled: true
56
+ EnforcedStyle: same_line
57
+
58
+ Layout/MultilineHashKeyLineBreaks:
59
+ Enabled: true
60
+
61
+ Layout/MultilineMethodArgumentLineBreaks:
62
+ Enabled: true
63
+
64
+ Layout/MultilineMethodCallIndentation:
65
+ EnforcedStyle: indented_relative_to_receiver
66
+
67
+ Layout/SingleLineBlockChain:
68
+ Enabled: true
69
+
70
+ Layout/SpaceAroundEqualsInParameterDefault:
71
+ EnforcedStyle: no_space
72
+
73
+ Layout/SpaceAroundOperators:
74
+ EnforcedStyleForExponentOperator: space
75
+
76
+ Layout/SpaceBeforeBrackets:
77
+ Enabled: true
78
+
79
+ Layout/SpaceInsideHashLiteralBraces:
80
+ EnforcedStyle: no_space
81
+
82
+ Layout/TrailingWhitespace:
83
+ AllowInHeredoc: true
84
+
85
+ Lint/AmbiguousAssignment:
86
+ Enabled: true
87
+
88
+ Lint/AmbiguousOperatorPrecedence:
89
+ Enabled: true
90
+
91
+ Lint/AmbiguousRange:
92
+ Enabled: true
93
+ RequireParenthesesForMethodChains: true
94
+
95
+ Lint/AssignmentInCondition:
96
+ AllowSafeAssignment: false
97
+
98
+ Lint/ConstantOverwrittenInRescue:
99
+ Enabled: true
100
+
101
+ Lint/DeprecatedConstants:
102
+ Enabled: true
103
+
104
+ Lint/DuplicateBranch:
105
+ Enabled: true
106
+ IgnoreLiteralBranches: true
107
+ IgnoreConstantBranches: true
108
+
109
+ Lint/DuplicateMagicComment:
110
+ Enabled: true
111
+
112
+ Lint/DuplicateRegexpCharacterClassElement:
113
+ Enabled: true
114
+
115
+ Lint/EmptyBlock:
116
+ Enabled: true
117
+
118
+ Lint/EmptyClass:
119
+ Enabled: true
120
+ AllowComments: true
121
+
122
+ Lint/EmptyInPattern:
123
+ Enabled: true
124
+
125
+ Lint/HeredocMethodCallPosition:
126
+ Enabled: true
127
+
128
+ Lint/IncompatibleIoSelectWithFiberScheduler:
129
+ Enabled: false
130
+
131
+ Lint/LambdaWithoutLiteralBlock:
132
+ Enabled: true
133
+
134
+ Lint/NoReturnInBeginEndBlocks:
135
+ Enabled: true
136
+
137
+ Lint/NonAtomicFileOperation:
138
+ Enabled: true
139
+
140
+ Lint/NumberedParameterAssignment:
141
+ Enabled: true
142
+
143
+ Lint/OrAssignmentToConstant:
144
+ Enabled: true
145
+
146
+ Lint/RedundantDirGlobSort:
147
+ Enabled: true
148
+
149
+ Lint/RedundantSplatExpansion:
150
+ AllowPercentLiteralArrayArgument: false
151
+
152
+ Lint/RefinementImportMethods:
153
+ Enabled: true
154
+
155
+ Lint/RequireRangeParentheses:
156
+ Enabled: true
157
+
158
+ Lint/RequireRelativeSelfPath:
159
+ Enabled: true
160
+
161
+ Lint/SymbolConversion:
162
+ Enabled: true
163
+
164
+ Lint/ToEnumArguments:
165
+ Enabled: true
166
+
167
+ Lint/TripleQuotes:
168
+ Enabled: true
169
+
170
+ Lint/UnexpectedBlockArity:
171
+ Enabled: true
172
+
173
+ Lint/UnmodifiedReduceAccumulator:
174
+ Enabled: true
175
+
176
+ Lint/UnusedBlockArgument:
177
+ AutoCorrect: false
178
+
179
+ Lint/UnusedMethodArgument:
180
+ AutoCorrect: false
181
+
182
+ Lint/UselessRescue:
183
+ Enabled: true
184
+
185
+ Lint/UselessRuby2Keywords:
186
+ Enabled: true
187
+
188
+ Metrics:
189
+ Enabled: false
190
+
191
+ Naming/BlockForwarding:
192
+ Enabled: true
193
+
194
+ Naming/InclusiveLanguage:
195
+ Enabled: false
196
+
197
+ Security/CompoundHash:
198
+ Enabled: true
199
+
200
+ Security/Eval:
201
+ Enabled: false
202
+
203
+ Security/IoMethods:
204
+ Enabled: true
205
+
206
+ Style/AccessorGrouping:
207
+ EnforcedStyle: separated
208
+
209
+ Style/ArgumentsForwarding:
210
+ Enabled: false
211
+
212
+ Style/ArrayIntersect:
213
+ Enabled: true
214
+
215
+ Style/AutoResourceCleanup:
216
+ Enabled: true
217
+
218
+ Style/CollectionCompact:
219
+ Enabled: true
220
+
221
+ Style/CollectionMethods:
222
+ Enabled: true
223
+
224
+ Style/ComparableClamp:
225
+ Enabled: true
226
+
227
+ Style/ConcatArrayLiterals:
228
+ Enabled: true
229
+
230
+ Style/DirEmpty:
231
+ Enabled: true
232
+
233
+ Style/DocumentDynamicEvalDefinition:
234
+ Enabled: false
235
+
236
+ Style/Documentation:
237
+ Enabled: false
238
+
239
+ Style/DocumentationMethod:
240
+ Enabled: false
241
+
242
+ Style/DoubleNegation:
243
+ EnforcedStyle: forbidden
244
+
245
+ Style/EmptyHeredoc:
246
+ Enabled: true
247
+
248
+ Style/EmptyMethod:
249
+ EnforcedStyle: expanded
250
+
251
+ Style/EndlessMethod:
252
+ Enabled: true
253
+ EnforcedStyle: disallow
254
+
255
+ Style/EnvHome:
256
+ Enabled: true
257
+
258
+ Style/FetchEnvVar:
259
+ Enabled: false
260
+
261
+ Style/FileEmpty:
262
+ Enabled: true
263
+
264
+ Style/FileRead:
265
+ Enabled: true
266
+
267
+ Style/FileWrite:
268
+ Enabled: true
269
+
270
+ Style/FormatString:
271
+ EnforcedStyle: percent
272
+
273
+ Style/FrozenStringLiteralComment:
274
+ Enabled: false
275
+
276
+ Style/HashConversion:
277
+ Enabled: true
278
+
279
+ Style/HashExcept:
280
+ Enabled: true
281
+
282
+ Style/HashSyntax:
283
+ EnforcedShorthandSyntax: never
284
+
285
+ Style/IfWithBooleanLiteralBranches:
286
+ Enabled: true
287
+
288
+ Style/ImplicitRuntimeError:
289
+ Enabled: true
290
+
291
+ Style/InPatternThen:
292
+ Enabled: true
293
+
294
+ Style/IpAddresses:
295
+ Enabled: true
296
+
297
+ Style/MagicCommentFormat:
298
+ Enabled: true
299
+
300
+ Style/MapCompactWithConditionalBlock:
301
+ Enabled: true
302
+
303
+ Style/MapToHash:
304
+ Enabled: true
305
+
306
+ Style/MapToSet:
307
+ Enabled: true
308
+
309
+ Style/MethodCallWithArgsParentheses:
310
+ Enabled: true
311
+ EnforcedStyle: omit_parentheses
312
+ AllowParenthesesInMultilineCall: true
313
+ AllowParenthesesInChaining: true
314
+ AllowParenthesesInCamelCaseMethod: true
315
+
316
+ Style/MethodDefParentheses:
317
+ EnforcedStyle: require_no_parentheses_except_multiline
318
+
319
+ Style/MinMaxComparison:
320
+ Enabled: true
321
+
322
+ Style/MultilineBlockChain:
323
+ Enabled: false
324
+
325
+ Style/MultilineInPatternThen:
326
+ Enabled: true
327
+
328
+ Style/NegatedIfElseCondition:
329
+ Enabled: true
330
+
331
+ Style/NestedFileDirname:
332
+ Enabled: true
333
+
334
+ Style/NestedParenthesizedCalls:
335
+ Enabled: false
336
+
337
+ Style/NilLambda:
338
+ Enabled: true
339
+
340
+ Style/NonNilCheck:
341
+ Enabled: false
342
+
343
+ Style/NumberedParameters:
344
+ Enabled: true
345
+ EnforcedStyle: disallow
346
+
347
+ Style/NumberedParametersLimit:
348
+ Enabled: true
349
+
350
+ Style/ObjectThen:
351
+ Enabled: true
352
+
353
+ Style/OpenStructUse:
354
+ Enabled: false
355
+
356
+ Style/OperatorMethodCall:
357
+ Enabled: true
358
+
359
+ Style/OptionHash:
360
+ Enabled: true
361
+
362
+ Style/QuotedSymbols:
363
+ Enabled: true
364
+
365
+ Style/RedundantArgument:
366
+ Enabled: false
367
+
368
+ Style/RedundantConstantBase:
369
+ Enabled: false
370
+
371
+ Style/RedundantDoubleSplatHashBraces:
372
+ Enabled: true
373
+
374
+ Style/RedundantEach:
375
+ Enabled: true
376
+
377
+ Style/RedundantException:
378
+ Enabled: false
379
+
380
+ Style/RedundantHeredocDelimiterQuotes:
381
+ Enabled: true
382
+
383
+ Style/RedundantInitialize:
384
+ Enabled: true
385
+
386
+ Style/RedundantParentheses:
387
+ Enabled: false
388
+
389
+ Style/RedundantSelfAssignmentBranch:
390
+ Enabled: true
391
+
392
+ Style/RedundantStringEscape:
393
+ Enabled: true
394
+
395
+ Style/RegexpLiteral:
396
+ EnforcedStyle: percent_r
397
+
398
+ Style/ReturnNil:
399
+ Enabled: true
400
+
401
+ Style/SelectByRegexp:
402
+ Enabled: true
403
+
404
+ Style/SingleLineMethods:
405
+ AllowIfMethodIsEmpty: false
406
+
407
+ Style/StaticClass:
408
+ Enabled: true
409
+
410
+ Style/StringChars:
411
+ Enabled: true
412
+
413
+ Style/StringHashKeys:
414
+ Enabled: false
415
+
416
+ Style/SwapValues:
417
+ Enabled: true
418
+
419
+ Style/SymbolArray:
420
+ EnforcedStyle: brackets
421
+
422
+ Style/TernaryParentheses:
423
+ EnforcedStyle: require_parentheses_when_complex
424
+ AllowSafeAssignment: false
425
+
426
+ Style/TopLevelMethodDefinition:
427
+ Enabled: true
428
+
429
+ Style/TrailingCommaInArguments:
430
+ Enabled: true
431
+ EnforcedStyleForMultiline: no_comma
432
+
433
+ Style/TrailingCommaInArrayLiteral:
434
+ Enabled: true
435
+ EnforcedStyleForMultiline: no_comma
436
+
437
+ Style/TrailingCommaInBlockArgs:
438
+ Enabled: true
439
+
440
+ Style/TrailingCommaInHashLiteral:
441
+ Enabled: true
442
+ EnforcedStyleForMultiline: no_comma
443
+
444
+ Style/UnlessLogicalOperators:
445
+ EnforcedStyle: forbid_logical_operators
446
+
447
+ Style/WordArray:
448
+ EnforcedStyle: brackets
449
+
450
+ Style/YodaCondition:
451
+ Enabled: true
452
+ EnforcedStyle: forbid_for_all_comparison_operators
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ <!--[//]: # (
4
+ ## <Release number> <Date YYYY-MM-DD>
5
+ ### Breaking changes
6
+ ### Deprecations
7
+ ### New features
8
+ ### Bug fixes
9
+ )-->
10
+
11
+ ## 1.0.0 2023-07-24
12
+
13
+ First release. Refer to [README.md](README.md) for the full documentation.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in prova.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rubocop", "~> 1.21"
11
+ gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
12
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Moku S.r.l., Nicolò Greggio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # Protobuf Transpiler
2
+
3
+ A protobuf transpiler and annotator for Rails applications.
4
+
5
+ This gem provides a quick way to generate annotated ruby stubs for protobufs leveraging [Ruby gRPC Tools](https://github.com/grpc/grpc/tree/master/src/ruby/tools#ruby-grpc-tools), adopting an opinionated Rails oriented approach.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'protobuf_transpiler', '~> 1.0'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```bash
18
+ bundle
19
+ ```
20
+
21
+
22
+ ## Usage
23
+
24
+ This gem provides two rake tasks, `grpc_stubs:generate` and `grpc_stubs:annotate`. `generate` transpiles all `.proto` files nested in a `public` folder looking in the `$LOAD_PATH`, putting the generated ruby stubs in `app/stubs`, respecting the inner nesting. `annotate` annotates all the generated stubs with a comment section leveraging reflection.
25
+
26
+ Beware that at the moment this gem does not support nested messages definition.
27
+
28
+ ### Generate
29
+ To generate the stubs simply run:
30
+ ```bash
31
+ rake grpc_stubs:generate
32
+ ```
33
+ The task accepts two optional positional arguments, `annotate` and `keep_require` which default respectively to `'yes'` and `'no'`.
34
+ This means that by default the `generate` task also runs the `annotate` one, and the behavior can be changed by specifying the first argument as `'no'`. Furthermore the default behavior of `generate` removes all the `require ...` generated by `grpc_tools_ruby_protoc`; if, for any reason, you may want to keep them, you need to specify the second argument as `'yes'` (which implies you need to explicitly state the first parameter, even if you want to keep the default behavior).
35
+ Finally, following the stubs generation, the task also creates a ruby file for all the proto packages, which corresponds to the created folders in `app/stubs`, containing `require_relative` instructions to the corresponding stubs. This allows `zeitwerk` to work properly despite `grpc_tools_ruby_protoc` not respecting the naming conventions.
36
+
37
+ For example if you have a gem defining proto files with this structure:
38
+ ```
39
+ public
40
+ ├── mod1
41
+ │ └── sample1.proto
42
+ ├── mod2
43
+ │ └── sample2.proto
44
+ ```
45
+ you will get the follwing structure nested in `app/stubs`
46
+ ```
47
+ app/stubs
48
+ ├── mod1
49
+ │ ├── sample1_pb.rb
50
+ │ └── sample1_services_pb.rb
51
+ ├── mod1.rb
52
+ ├── mod2
53
+ │ ├── sample2_pb.rb
54
+ │ └── sample2_services_pb.rb
55
+ ├── mod2.rb
56
+
57
+ ```
58
+
59
+ ### Annotate
60
+ To annotate generated stubs simply run:
61
+ ```bash
62
+ rake grpc_stubs:annotate
63
+ ```
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
+
66
+ Here's an example of annotations of some messages:
67
+ ```
68
+ # ===== Protobuf Annotation =====
69
+ # Test::GetJobReq
70
+ # id: uint64
71
+ # Test::GetJobResp
72
+ # id: uint64
73
+ # name: string
74
+ # surname: string
75
+ # ===== Protobuf Annotation =====
76
+ ```
77
+ and some rpcs:
78
+ ```
79
+ # ===== Protobuf Annotation =====
80
+ # Test::Jobs
81
+ # GetJob(Test::GetJobReq): Test::GetJobResp
82
+ # Test::Another
83
+ # GetNew(Test::GetJobReq): Test::GetJobResp
84
+ # ===== Protobuf Annotation =====
85
+ ```
86
+
87
+ ## Future extensions
88
+ - Support nested messages definition
89
+
90
+ ## Version numbers
91
+
92
+ Protobuf Transpiler loosely follows [Semantic Versioning](https://semver.org/), with a hard guarantee that breaking changes to the public API will always coincide with an increase to the `MAJOR` number.
93
+
94
+ Version numbers are in three parts: `MAJOR.MINOR.PATCH`.
95
+
96
+ - Breaking changes to the public API increment the `MAJOR`. There may also be changes that would otherwise increase the `MINOR` or the `PATCH`.
97
+ - Additions, deprecations, and "big" non breaking changes to the public API increment the `MINOR`. There may also be changes that would otherwise increase the `PATCH`.
98
+ - Bug fixes and "small" non breaking changes to the public API increment the `PATCH`.
99
+
100
+ Notice that any feature deprecated by a minor release can be expected to be removed by the next major release.
101
+
102
+ ## Changelog
103
+
104
+ Full list of changes in [CHANGELOG.md](CHANGELOG.md)
105
+
106
+
107
+ ## Contributing
108
+
109
+ Bug reports and pull requests are welcome on GitHub at https://github.com/moku-io/protobuf_transpiler.
110
+
111
+ ## License
112
+
113
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rubocop/rake_task"
5
+
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :rubocop
9
+
10
+ import(*Dir[File.join(File.dirname(__FILE__), 'lib/tasks', '**/*.rake')])
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ # Make tasks visible for Rails also when used as gem.
5
+ Dir[File.join(File.dirname(__FILE__), '..', 'tasks', '**/*.rake')].each { |rake| load rake }
6
+ Dir[File.join(File.dirname(__FILE__), '..', '..', 'tasks', '**/*.rake')].each { |rake| load rake }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ProtobufTranspiler
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "protobuf_transpiler/version"
4
+
5
+ module ProtobufTranspiler
6
+ require_relative 'railtie'
7
+
8
+ class << self
9
+ def generate_stubs(keep_require = false)
10
+ paths = $LOAD_PATH.map { |p| "#{p}/**/public/**/*.proto" }
11
+ proto_files = Dir[*paths].join ' '
12
+ proto_paths = proto_files
13
+ .split.map { |p| p.sub %r{(?<=public).*}, '' }
14
+ .uniq.join ' '
15
+ out_path = "#{Rails.root}/app/stubs/"
16
+ FileUtils.mkdir_p out_path
17
+ `grpc_tools_ruby_protoc --ruby_out=#{out_path} --grpc_out=#{out_path} #{proto_files} -I #{proto_paths}`
18
+
19
+ # remove possibly useless require from stub file
20
+ unless keep_require
21
+ Dir['app/stubs/**/*.rb'].each do |fp|
22
+ f = File.read fp
23
+ File.write fp, (f.sub /\n(require.*?'\n)+/, '')
24
+ end
25
+ end
26
+
27
+ # make zeitwerk happy
28
+ Dir['app/stubs/**']
29
+ .filter { |f| File.directory? f }
30
+ .each { |dir|
31
+ requires = Dir.chdir dir do
32
+ curr_dir = Dir.pwd.split('/').last
33
+ Dir['*.rb'].map { |s| "require_relative './#{curr_dir}/#{s.sub(/.rb$/, '')}'" }
34
+ end
35
+ File.write "#{dir}.rb", requires.join("\n")
36
+ }
37
+ end
38
+
39
+ def annotate_stubs
40
+ require 'active_support/core_ext/string/inflections'
41
+
42
+ Dir['app/stubs/**/*.rb']
43
+ .map { |s| File.absolute_path s }
44
+ .each { |f| require f }
45
+
46
+ stubs_modules = Dir['app/stubs/*.rb']
47
+ .map { |s| s.sub('app/stubs/', '') }
48
+ .map { |s| s.sub '.rb', '' }
49
+ .uniq
50
+ .map { |c| Object.const_get c.camelize }
51
+
52
+ stubs_modules.each do |m|
53
+ out = m
54
+ .constants
55
+ .map { |c| m.const_get c }
56
+ .each_with_object({ messages: [], services: [] }) { |c, acc|
57
+ if c.is_a? Class
58
+ acc[:messages] << class_annotations(c)
59
+ else
60
+ acc[:services] << module_annotations(c)
61
+ end
62
+ }
63
+ types_file, services_file = Dir["app/stubs/#{m.name.downcase}/*.rb"]
64
+ .sort_by { |s| s.scan('services').count }
65
+ [types_file, services_file]
66
+ .zip([out[:messages], out[:services]])
67
+ .each { |file, content| annotate_file file, content }
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ ANNOTATE_DELIMITER = '===== Protobuf Annotation ====='
74
+
75
+ def class_annotations c
76
+ c
77
+ .descriptor.entries.map { |d| "\t#{d.name}: #{d.type}" }
78
+ .prepend("#{c.name}")
79
+ .join "\n"
80
+ end
81
+
82
+ def module_annotations m
83
+ m
84
+ .const_get('Service')
85
+ .rpc_descs.map { |_, d| "\t#{d.name}(#{d.input}): #{d.output}" }
86
+ .prepend("#{m.name}")
87
+ .join "\n"
88
+ end
89
+
90
+ def annotate_file file, content
91
+ old_content = File.read file
92
+ content = content.join("\n").gsub(%r{^}, '# ')
93
+ new_content = if old_content.match? ANNOTATE_DELIMITER
94
+ # replace annotation content
95
+ old_content.sub %r{(?<=#{ANNOTATE_DELIMITER})(.|\n)*?(?=##{ANNOTATE_DELIMITER})}, "\n#{content}\n"
96
+ else
97
+ # find first spot after comments
98
+ # add and fill annotation
99
+ old_content.sub %r{^[^#]}, "\n# #{ANNOTATE_DELIMITER}\n#{content}\n# #{ANNOTATE_DELIMITER}\n\n"
100
+ end
101
+ File.write file, new_content
102
+ end
103
+ end
104
+ end
data/lib/railtie.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'protobuf_transpiler'
2
+ require 'rails'
3
+
4
+ module ProtobufTranspiler
5
+ class Railtie < Rails::Railtie
6
+ railtie_name :protobuf_transpiler
7
+
8
+ rake_tasks do
9
+ path = File.expand_path(__dir__)
10
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ namespace :grpc_stubs do
2
+ desc 'Generate stubs for all .proto files (looking into entire LOAD_PATH)'
3
+ task :generate, [:annotate, :keep_require] do |_, args|
4
+ args.with_defaults annotate: :yes, keep_require: :no
5
+ require_relative '../protobuf_transpiler'
6
+ ProtobufTranspiler.generate_stubs args[:keep_require].to_sym == :yes
7
+ ProtobufTranspiler.annotate_stubs unless args[:annotate].to_sym == :no
8
+ end
9
+
10
+ desc 'Annotate generated stubs'
11
+ task :annotate do
12
+ require_relative '../protobuf_transpiler'
13
+ ProtobufTranspiler.annotate_stubs
14
+ end
15
+ end
16
+
17
+
18
+
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: protobuf_transpiler
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Moku S.r.l.
8
+ - Nicolò Greggio
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2023-07-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: google-protobuf
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.23'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 3.23.3
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '3.23'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.23.3
34
+ - !ruby/object:Gem::Dependency
35
+ name: grpc
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.56'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.56'
48
+ - !ruby/object:Gem::Dependency
49
+ name: grpc-tools
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.56'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.56'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rails
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '7.0'
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 7.0.6
72
+ type: :runtime
73
+ prerelease: false
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "~>"
77
+ - !ruby/object:Gem::Version
78
+ version: '7.0'
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 7.0.6
82
+ description: This gem provides a quick way to generate annotated ruby stubs for protobufs
83
+ leveraging Ruby gRPC Tools, adopting an opinionated Rails oriented approach.
84
+ email:
85
+ - info@moku.io
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".rubocop.yml"
91
+ - CHANGELOG.md
92
+ - Gemfile
93
+ - LICENSE
94
+ - README.md
95
+ - Rakefile
96
+ - lib/protobuf_transpiler.rb
97
+ - lib/protobuf_transpiler/tasks.rb
98
+ - lib/protobuf_transpiler/version.rb
99
+ - lib/railtie.rb
100
+ - lib/tasks/grpc_stubs.rake
101
+ homepage: https://github.com/moku-io/protobuf_transpiler
102
+ licenses:
103
+ - MIT
104
+ metadata:
105
+ homepage_uri: https://github.com/moku-io/protobuf_transpiler
106
+ source_code_uri: https://github.com/moku-io/protobuf_transpiler
107
+ changelog_uri: https://github.com/moku-io/protobuf_transpiler/blob/master/CHANGELOG.md
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 2.6.0
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.4.6
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: A protobuf transpiler and annotator for Rails applications.
127
+ test_files: []