grpc-rest 0.1.25 → 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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +2 -41
  3. data/.rubocop.yml +3 -0
  4. data/CHANGELOG +2 -0
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +21 -10
  7. data/README.md +7 -8
  8. data/bin/protoc-gen-rails +6 -0
  9. data/grpc-rest.gemspec +4 -1
  10. data/lib/generator/controller.rb.erb +27 -0
  11. data/lib/generator/grpc.rb.erb +9 -0
  12. data/lib/generator/method.rb +96 -0
  13. data/lib/generator/output.rb +28 -0
  14. data/lib/generator/plugin_pb.rb +25 -0
  15. data/lib/generator/service.rb +36 -0
  16. data/lib/generator.rb +88 -0
  17. data/lib/grpc_rest/version.rb +3 -1
  18. data/lib/grpc_rest.rb +35 -37
  19. data/{protoc-gen-rails/testdata/base/app/controllers/my_service_controller.rb → spec/__snapshots__/service.snap} +33 -27
  20. data/spec/base_interceptor_spec.rb +6 -3
  21. data/spec/{protoc-gen-openapiv2 → gen/protoc-gen-openapiv2}/options/annotations_pb.rb +5 -4
  22. data/spec/{protoc-gen-openapiv2 → gen/protoc-gen-openapiv2}/options/openapiv2_pb.rb +30 -29
  23. data/spec/gen/test_pb.rb +15 -0
  24. data/spec/gen/test_service_pb.rb +23 -0
  25. data/spec/gen/test_service_services_pb.rb +26 -0
  26. data/spec/generator_spec.rb +49 -0
  27. data/spec/grpc_rest_spec.rb +65 -25
  28. data/spec/gruf_spec.rb +4 -3
  29. data/spec/spec_helper.rb +8 -6
  30. data/spec/test_service_services_pb.rb +2 -1
  31. data/spec/testdata/base/app/controllers/my_service_controller.rb +65 -0
  32. data/spec/testdata/no_service/.keep +0 -0
  33. metadata +89 -25
  34. data/protoc-gen-rails/.goreleaser.yml +0 -27
  35. data/protoc-gen-rails/LICENSE +0 -21
  36. data/protoc-gen-rails/go.mod +0 -25
  37. data/protoc-gen-rails/go.sum +0 -49
  38. data/protoc-gen-rails/internal/output.go +0 -165
  39. data/protoc-gen-rails/internal/parse.go +0 -101
  40. data/protoc-gen-rails/internal/utils.go +0 -57
  41. data/protoc-gen-rails/main.go +0 -104
  42. data/protoc-gen-rails/main_test.go +0 -158
  43. /data/{protoc-gen-rails/testdata/no_service/.keep → spec/__snapshots__/no_service.snap} +0 -0
  44. /data/{protoc-gen-rails → spec}/google-deps/google/api/annotations.proto +0 -0
  45. /data/{protoc-gen-rails → spec}/google-deps/google/api/http.proto +0 -0
  46. /data/{protoc-gen-rails → spec}/google-deps/protoc-gen-openapiv2/options/annotations.proto +0 -0
  47. /data/{protoc-gen-rails → spec}/google-deps/protoc-gen-openapiv2/options/openapiv2.proto +0 -0
  48. /data/{protoc-gen-rails → spec}/testdata/base/config/routes/grpc.rb +0 -0
  49. /data/{protoc-gen-rails → spec}/testdata/test.proto +0 -0
  50. /data/{protoc-gen-rails → spec}/testdata/test_service.proto +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38281059f56037899cfff4869307d014ccbc2ec48556d5a8354367d166e06aec
4
- data.tar.gz: 1f952b2758520d3e5d9763751cb61ec4ec5397f299a75f8513c08a1168f9d9e7
3
+ metadata.gz: 57ad95cccdb8e4034e4635b2f373dd3db5e31ff4e4a5bddfbd6d977f9b93bf29
4
+ data.tar.gz: '09b6320949f7894835e1596721ea0f38df5543998b19a7598172be1f1b79d188'
5
5
  SHA512:
6
- metadata.gz: 88661401dcd71922e256ad80ec5767e41c6d346062ea87b5d55d2f27395f55c3e6a71cfd997f914ba9702f6f64f569049720bbd52814ffda5546237fae089f83
7
- data.tar.gz: 9b9ab5e77e9c2dc8f7523ee1c2306607020adb4c10dd5728bd5116493351277fdf779fff2a83ba848bcfad35172afe8b67dbf76ea824fe524af5637b1c2e96aa
6
+ metadata.gz: 605c7f2ea415104673b4693acaf5a1d90079172affb814bc4684ddbaa9698c2558abaaff19355b80e2cbced8715e7367b58541b4e49bf341d436b540b7a3d5ec
7
+ data.tar.gz: e4ff129327451f1101a8a3dec623a4a80b4e8eec3882f6d9ab0f52ed450c4a403226178391633001c4f3f6a3dbecc8130ae7afd55adc9e74102dfd878645305a
@@ -8,23 +8,6 @@ on:
8
8
  workflow_dispatch:
9
9
 
10
10
  jobs:
11
- test-go:
12
- runs-on: [ubuntu-latest]
13
- steps:
14
- - name: Checkout code
15
- uses: actions/checkout@v4
16
- with:
17
- fetch-depth: 0
18
- - name: Setup Go
19
- uses: actions/setup-go@v2
20
- with:
21
- go-version: '1.21'
22
- - name: Install Protoc
23
- uses: arduino/setup-protoc@v2
24
- - run: git reset --hard
25
- - run: git clean -f -d
26
- - run: cd protoc-gen-rails && go test ./...
27
-
28
11
  test-ruby:
29
12
  runs-on: [ubuntu-latest]
30
13
  steps:
@@ -37,28 +20,6 @@ jobs:
37
20
  with:
38
21
  ruby-version: '3.3'
39
22
  bundler-cache: true
23
+ - name: Install Protoc
24
+ uses: arduino/setup-protoc@v2
40
25
  - run: bundle exec rspec
41
-
42
- build_and_deploy:
43
- needs: [test-go, test-ruby]
44
- runs-on: [ubuntu-latest]
45
- steps:
46
- - name: Checkout code
47
- uses: actions/checkout@v4
48
- with:
49
- fetch-depth: 0
50
- - name: Setup Go
51
- uses: actions/setup-go@v2
52
- with:
53
- go-version: '1.21'
54
- - run: git reset --hard
55
- - run: git clean -f -d
56
- - name: Run GoReleaser
57
- uses: goreleaser/goreleaser-action@v3
58
- with:
59
- distribution: goreleaser
60
- version: latest
61
- workdir: ./protoc-gen-rails
62
- args: release --clean
63
- env:
64
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/.rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ AllCops:
2
+ Exclude:
3
+ - "**/*_pb.rb"
data/CHANGELOG CHANGED
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
+ - Rewrite protobuf plugin in Ruby.
11
+
10
12
  # 0.1.25 - 2025-04-30
11
13
  - Fix for crash when parsing map fields
12
14
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grpc-rest (0.1.25)
4
+ grpc-rest (0.2.0)
5
+ google-protobuf (>= 4.30.2)
5
6
  grpc
6
7
  rails (>= 6.0)
7
8
 
@@ -73,7 +74,10 @@ GEM
73
74
  i18n (>= 1.6, < 2)
74
75
  minitest (>= 5.1)
75
76
  tzinfo (~> 2.0)
77
+ awesome_print (1.9.2)
78
+ bigdecimal (3.1.9)
76
79
  builder (3.2.4)
80
+ byebug (12.0.0)
77
81
  concurrent-ruby (1.2.3)
78
82
  crass (1.0.6)
79
83
  date (3.3.4)
@@ -81,15 +85,13 @@ GEM
81
85
  erubi (1.12.0)
82
86
  globalid (1.2.1)
83
87
  activesupport (>= 6.1)
84
- google-protobuf (3.25.3-arm64-darwin)
85
- google-protobuf (3.25.3-x86_64-linux)
86
- googleapis-common-protos-types (1.14.0)
87
- google-protobuf (~> 3.18)
88
- grpc (1.62.0-arm64-darwin)
89
- google-protobuf (~> 3.25)
90
- googleapis-common-protos-types (~> 1.0)
91
- grpc (1.62.0-x86_64-linux)
92
- google-protobuf (~> 3.25)
88
+ google-protobuf (4.30.2-arm64-darwin)
89
+ bigdecimal
90
+ rake (>= 13)
91
+ googleapis-common-protos-types (1.19.0)
92
+ google-protobuf (>= 3.18, < 5.a)
93
+ grpc (1.71.0-arm64-darwin)
94
+ google-protobuf (>= 3.25, < 5.0)
93
95
  googleapis-common-protos-types (~> 1.0)
94
96
  grpc-tools (1.64.0)
95
97
  gruf (2.20.0)
@@ -162,6 +164,10 @@ GEM
162
164
  thor (~> 1.0)
163
165
  zeitwerk (~> 2.5)
164
166
  rake (13.2.1)
167
+ rspec (3.13.0)
168
+ rspec-core (~> 3.13.0)
169
+ rspec-expectations (~> 3.13.0)
170
+ rspec-mocks (~> 3.13.0)
165
171
  rspec-core (3.13.0)
166
172
  rspec-support (~> 3.13.0)
167
173
  rspec-expectations (3.13.0)
@@ -178,6 +184,9 @@ GEM
178
184
  rspec-expectations (~> 3.13)
179
185
  rspec-mocks (~> 3.13)
180
186
  rspec-support (~> 3.13)
187
+ rspec-snapshot (2.0.3)
188
+ awesome_print (> 1.0.0)
189
+ rspec (> 3.0.0)
181
190
  rspec-support (3.13.1)
182
191
  slop (4.10.1)
183
192
  thor (1.3.1)
@@ -194,9 +203,11 @@ PLATFORMS
194
203
  x86_64-linux
195
204
 
196
205
  DEPENDENCIES
206
+ byebug
197
207
  grpc-rest!
198
208
  gruf
199
209
  rspec-rails
210
+ rspec-snapshot
200
211
 
201
212
  BUNDLED WITH
202
213
  2.5.6
data/README.md CHANGED
@@ -23,15 +23,15 @@ The protobuf generator uses the same annotations as [grpc-gateway](https://githu
23
23
 
24
24
  ## Installation
25
25
 
26
- First, download `protoc-gen-rails` from the releases page on the right and unzip it. Ensure the binary is somewhere in your PATH.
27
-
28
- Then, add the following to your `Gemfile`:
26
+ Add the following to your `Gemfile`:
29
27
 
30
28
  ```ruby
31
29
  gem 'grpc-rest'
32
30
  ```
33
31
 
34
- and run `bundle install`.
32
+ and run `bundle install`. Then when using `protoc` or `buf generate`, ensure you prefix the command with `bundle exec`, e.g.
33
+
34
+ `bundle exec buf generate`
35
35
 
36
36
  ## Example
37
37
 
@@ -78,6 +78,9 @@ plugins:
78
78
  - paths=source_relative
79
79
  - name: rails
80
80
  out: .
81
+ opt:
82
+ # this should be the same directory as the output of your Ruby plugin
83
+ - require=app/gen
81
84
  ```
82
85
 
83
86
  Then, you can run `buf generate` to generate the Ruby files. This will generate:
@@ -172,10 +175,6 @@ module Interceptors
172
175
  end
173
176
  ```
174
177
 
175
- ## To Do
176
-
177
- * Replace Go implementation with Ruby (+ executable)
178
-
179
178
  ## Contributing
180
179
 
181
180
  Bug reports and pull requests are welcome on GitHub at https://github.com/flipp-oss/grpc-rest.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/generator'
5
+
6
+ $stdout << ProtocGenRails.process($stdin.read)
data/grpc-rest.gemspec CHANGED
@@ -18,9 +18,12 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
+ spec.add_runtime_dependency('google-protobuf', '>= 4.30.2')
21
22
  spec.add_runtime_dependency('grpc')
22
23
  spec.add_runtime_dependency('rails', '>= 6.0')
23
24
 
24
- spec.add_development_dependency('rspec-rails')
25
+ spec.add_development_dependency('byebug')
25
26
  spec.add_development_dependency('gruf')
27
+ spec.add_development_dependency('rspec-rails')
28
+ spec.add_development_dependency('rspec-snapshot')
26
29
  end
@@ -0,0 +1,27 @@
1
+ ####### THIS FILE IS AUTOMATICALLY GENERATED BY protoc-gen-rails. DO NOT MODIFY. #######
2
+
3
+ require 'grpc_rest'
4
+ class <%= service.name.demodulize %>Controller < ActionController::Base
5
+ protect_from_forgery with: :null_session
6
+
7
+ rescue_from StandardError do |e|
8
+ render json: GrpcRest.error_msg(e), status: :internal_server_error
9
+ end
10
+ rescue_from GRPC::BadStatus do |e|
11
+ render json: GrpcRest.error_msg(e), status: GrpcRest.grpc_http_status(e.code)
12
+ end
13
+ rescue_from ActionDispatch::Http::Parameters::ParseError, Google::Protobuf::TypeError do |e|
14
+ render json: GrpcRest.error_msg(e), status: :bad_request
15
+ end
16
+ METHOD_PARAM_MAP = <%= service.methods.to_h { |m| [m.name.underscore, m.path_info.map(&:to_h)]}.pretty_inspect %>.freeze
17
+
18
+ <% service.methods.each do |method| %>
19
+ def <%= method.name %>
20
+ fields = <%= method.request_type %>.descriptor.to_a.map(&:name)
21
+ parameters = request.parameters.to_h.deep_transform_keys(&:underscore)
22
+ grpc_request = GrpcRest.init_request(<%= method.request_type %>, parameters.slice(*fields))
23
+ GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["<%= method.name.underscore %>"], "<%= method.option_body %>", request.parameters)
24
+ render json: GrpcRest.send_request("<%= service.namespace %>::<%= service.name.classify %>", "<%= method.name.underscore %>", grpc_request, <%= method.rest_options.inspect %>)
25
+ end
26
+ <% end %>
27
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ ####### THIS FILE IS AUTOMATICALLY GENERATED BY protoc-gen-rails. DO NOT MODIFY. #######
4
+
5
+ <% services.each do |service| -%>
6
+ <% service.methods.each do |method| %>
7
+ <%= method.http_method %> '<%= method.sanitized_path %>' => '<%= service.name.demodulize.underscore %>#<%= method.name.underscore %>' <% -%>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ProtocGenRails
4
+ class Method
5
+ PathInfo = Struct.new(:name, :val, :split_name)
6
+
7
+ attr_accessor :http_method, :path, :path_info, :rest_options
8
+
9
+ # @param proto_method [Google::Protobuf::MethodDescriptor]
10
+ def initialize(proto_method)
11
+ @method = proto_method
12
+ @rest_options = extract_rest_options
13
+ @options = extract_options
14
+ @http_method, @path = method_and_path
15
+ @path_info = extract_path_info
16
+ end
17
+
18
+ # @return [String]
19
+ def option_body = @options&.body
20
+ # @return [String]
21
+ def name = @method.name.underscore
22
+
23
+ # @return [String]
24
+ def request_type
25
+ @method.input_type.name.split('.').map(&:camelcase).join('::')
26
+ end
27
+
28
+ # @return [String]
29
+ def sanitized_path
30
+ path = @path
31
+ re = /\{(.*?)}/
32
+ matches = path.scan(re)
33
+ matches.each do |match|
34
+ repl = match[0]
35
+ equal = repl.index('=')
36
+ repl = repl[0...equal] if equal
37
+ dot = repl.index('.')
38
+ repl = repl[(dot + 1)..] if dot
39
+ path = path.sub("{#{match[0]}}", "*#{repl}")
40
+ end
41
+ path
42
+ end
43
+
44
+ # @return [Google::Api::HttpRule]
45
+ def extract_options
46
+ return nil if @method.options.nil?
47
+
48
+ extension = Google::Protobuf::DescriptorPool.generated_pool.lookup('google.api.http')
49
+ extension.get(@method.options)
50
+ end
51
+
52
+ # @return [Hash]
53
+ def extract_rest_options
54
+ return nil if @method.options.nil?
55
+
56
+ extension = Google::Protobuf::DescriptorPool.generated_pool
57
+ .lookup('grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation')
58
+ result = extension.get(@method.options)
59
+ return {} if result.nil?
60
+
61
+ emit_defaults = result.extensions['x-grpc-rest-emit-defaults']&.bool_value || false
62
+ {
63
+ emit_defaults: emit_defaults
64
+ }
65
+ end
66
+
67
+ # @return [String, String]
68
+ def method_and_path
69
+ return if @options.nil?
70
+
71
+ if @options.pattern == :custom
72
+ [@options.custom.kind, @options.custom.path]
73
+ else
74
+ [@options.pattern, @options.send(@options.pattern)]
75
+ end
76
+ end
77
+
78
+ # @return [PathInfo]
79
+ def extract_path_info
80
+ @path.scan(/\{(.*?)}/).map do |match|
81
+ name = match[0]
82
+ val = ''
83
+ equal = name.index('=')
84
+ if equal
85
+ val = name[equal..]
86
+ name = name[0..equal - 1]
87
+ end
88
+ PathInfo.new(
89
+ name: name,
90
+ val: val,
91
+ split_name: name.split('.')
92
+ )
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ProtocGenRails
4
+ module Output
5
+ class << self
6
+ # @param files [Array<FileResult>]
7
+ # @return [String]
8
+ def response(files)
9
+ response = Google::Protobuf::Compiler::CodeGeneratorResponse.new
10
+ response.supported_features = Google::Protobuf::Compiler::CodeGeneratorResponse::Feature::FEATURE_PROTO3_OPTIONAL
11
+ files.each do |file|
12
+ response.file << Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(name: file.name,
13
+ content: file.content)
14
+ end
15
+ response.to_proto
16
+ end
17
+
18
+ # @param error [String]
19
+ def exit_with_error(error)
20
+ response = Google::Protobuf::Compiler::CodeGeneratorResponse.new
21
+ response.error = error
22
+ $stderr << "#{error}\n"
23
+ $stdout << response.to_proto
24
+ exit(1)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: google/protobuf/compiler/plugin.proto
5
+
6
+ require 'google/protobuf'
7
+
8
+ require 'google/protobuf/descriptor_pb'
9
+
10
+ descriptor_data = "\n%google/protobuf/compiler/plugin.proto\x12\x18google.protobuf.compiler\x1a google/protobuf/descriptor.proto\"F\n\x07Version\x12\r\n\x05major\x18\x01 \x01(\x05\x12\r\n\x05minor\x18\x02 \x01(\x05\x12\r\n\x05patch\x18\x03 \x01(\x05\x12\x0e\n\x06suffix\x18\x04 \x01(\t\"\x81\x02\n\x14\x43odeGeneratorRequest\x12\x18\n\x10\x66ile_to_generate\x18\x01 \x03(\t\x12\x11\n\tparameter\x18\x02 \x01(\t\x12\x38\n\nproto_file\x18\x0f \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\x12\x45\n\x17source_file_descriptors\x18\x11 \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\x12;\n\x10\x63ompiler_version\x18\x03 \x01(\x0b\x32!.google.protobuf.compiler.Version\"\x92\x03\n\x15\x43odeGeneratorResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\x12\x1a\n\x12supported_features\x18\x02 \x01(\x04\x12\x17\n\x0fminimum_edition\x18\x03 \x01(\x05\x12\x17\n\x0fmaximum_edition\x18\x04 \x01(\x05\x12\x42\n\x04\x66ile\x18\x0f \x03(\x0b\x32\x34.google.protobuf.compiler.CodeGeneratorResponse.File\x1a\x7f\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0finsertion_point\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x0f \x01(\t\x12?\n\x13generated_code_info\x18\x10 \x01(\x0b\x32\".google.protobuf.GeneratedCodeInfo\"W\n\x07\x46\x65\x61ture\x12\x10\n\x0c\x46\x45\x41TURE_NONE\x10\x00\x12\x1b\n\x17\x46\x45\x41TURE_PROTO3_OPTIONAL\x10\x01\x12\x1d\n\x19\x46\x45\x41TURE_SUPPORTS_EDITIONS\x10\x02\x42r\n\x1c\x63om.google.protobuf.compilerB\x0cPluginProtosZ)google.golang.org/protobuf/types/pluginpb\xaa\x02\x18Google.Protobuf.Compiler"
11
+
12
+ pool = Google::Protobuf::DescriptorPool.generated_pool
13
+ pool.add_serialized_file(descriptor_data)
14
+
15
+ module Google
16
+ module Protobuf
17
+ module Compiler
18
+ Version = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('google.protobuf.compiler.Version').msgclass
19
+ CodeGeneratorRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('google.protobuf.compiler.CodeGeneratorRequest').msgclass
20
+ CodeGeneratorResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('google.protobuf.compiler.CodeGeneratorResponse').msgclass
21
+ CodeGeneratorResponse::File = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('google.protobuf.compiler.CodeGeneratorResponse.File').msgclass
22
+ CodeGeneratorResponse::Feature = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('google.protobuf.compiler.CodeGeneratorResponse.Feature').enummodule
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'method'
4
+
5
+ module ProtocGenRails
6
+ class Service
7
+ attr_accessor :methods
8
+
9
+ # @param service_proto [Google::Protobuf::ServiceDescriptorProto]
10
+ # @param package [String]
11
+ def initialize(service_proto, package)
12
+ # see https://github.com/protocolbuffers/protobuf/issues/21091 for why this is needed
13
+ # this will return a Google::Protobuf::ServiceDescriptor
14
+ @service = Google::Protobuf::DescriptorPool.generated_pool.lookup("#{package}.#{service_proto.name}")
15
+ if @service.nil?
16
+ ProtocGenRails::Output.exit_with_error("Could not find generated service: #{package}.#{service_proto.name}")
17
+ end
18
+ @methods = []
19
+ @package = package
20
+ @service.each do |m|
21
+ # m is a Google::Protobuf::MethodDescriptor
22
+ @methods.push(ProtocGenRails::Method.new(m))
23
+ end
24
+ end
25
+
26
+ # @return [String]
27
+ def name
28
+ @service.name.split('.').map(&:camelcase).join('::').demodulize
29
+ end
30
+
31
+ # @return [String]
32
+ def namespace
33
+ @package.split('.').map(&:camelcase).join('::')
34
+ end
35
+ end
36
+ end
data/lib/generator.rb ADDED
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'google/protobuf'
4
+ require 'erb'
5
+ require 'active_support/all'
6
+ require 'google/protobuf/well_known_types'
7
+ require 'pp'
8
+
9
+ require_relative 'generator/output'
10
+ require_relative 'generator/service'
11
+ require_relative 'generator/plugin_pb'
12
+
13
+ module ProtocGenRails
14
+ FileResult = Struct.new(:name, :content)
15
+
16
+ class << self
17
+
18
+ # @param params [String]
19
+ def require_directories(params)
20
+ params.split(',').each do |param|
21
+ key, value = param.split('=')
22
+ next unless key == 'require'
23
+
24
+ dirs = value.split(',')
25
+ dirs.each do |v|
26
+ $LOAD_PATH.unshift(v)
27
+ dir = File.expand_path(v)
28
+ Dir["#{dir}/**/*.rb"].each { |file| require file }
29
+ end
30
+ end
31
+ end
32
+
33
+ # @param input [String]
34
+ # @return [String]
35
+ def process(input)
36
+ request = Google::Protobuf::Compiler::CodeGeneratorRequest.decode(input)
37
+ files = []
38
+
39
+ require_directories(request.parameter)
40
+
41
+ services = []
42
+ request.proto_file.each do |proto_file|
43
+ next if request.file_to_generate.exclude?(proto_file.name)
44
+ next if proto_file.service.none?
45
+
46
+ proto_file.service.each do |service_descriptor|
47
+ service = ProtocGenRails::Service.new(service_descriptor, proto_file.package)
48
+ services.push(service)
49
+ file = process_service(service)
50
+ files.push(file) if file
51
+ end
52
+ end
53
+ if files.any?
54
+ route_output = route_file(services)
55
+ files.push(route_output) if route_output
56
+ end
57
+ Output.response(files)
58
+ end
59
+
60
+ # @param service [ProtocGenRails::Service]
61
+ # @return [FileResult]
62
+ def process_service(service)
63
+ content = parse_erb('controller', { service: service })
64
+ FileResult.new(
65
+ content: content,
66
+ name: "app/controllers/#{service.name.underscore}_controller.rb"
67
+ )
68
+ end
69
+
70
+ # @param services [Array<ProtocGenRails::Service>]
71
+ # @return [FileResult]
72
+ def route_file(services)
73
+ content = parse_erb('grpc', { services: services })
74
+ FileResult.new(
75
+ name: 'config/routes/grpc.rb',
76
+ content: content
77
+ )
78
+ end
79
+
80
+ # @param filename [String]
81
+ # @param data [Object]
82
+ # @return [String]
83
+ def parse_erb(filename, data)
84
+ erb = File.read("#{__dir__}/generator/#{filename}.rb.erb")
85
+ ERB.new(erb, trim_mode: '-').result_with_hash(data.to_h)
86
+ end
87
+ end
88
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GrpcRest
2
- VERSION = '0.1.25'
4
+ VERSION = '0.2.0'
3
5
  end