protobuf_transpiler 1.1.3 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15fbfbb54281b38de5cfd351b52541f39ae5e242af25db502bc130c84bddf6d3
4
- data.tar.gz: 265c16629afd53e58cc88833c72cf7cf69a98c88b5cc51917bf732f04b4bbb27
3
+ metadata.gz: 5ae36cca017f8dc92d448d3312284e2462934a87b522675684d3e987e53e1029
4
+ data.tar.gz: 781b649dd1a6dcace6b68e9fea32efb5699c63008af53106f4a4b081b0b103ea
5
5
  SHA512:
6
- metadata.gz: d3103191a91d091d7e43afba1ca24a009c62a239960b238d41b474fe52e3958be6f138f3dbcac12d5abf0f8a6fad4d469a1886642a27a0763c557f3b519926b8
7
- data.tar.gz: '0380a204e36963f651e5963b61d3d39770b3ab11aed2ee5d696371a1648ebd0c68f8e38d265ee9d9663b4597cd24e5736fc50f57dfe5177f8dc301e43f0711d3'
6
+ metadata.gz: f9eedd08deb9598d3d6a978e57549ae8472e8129021e3d5d7a775c301b4198633c999c376ef6356755d358530e695b056e1c0a6d08b1601a650ae6d60c90dd15
7
+ data.tar.gz: 4fcd0154d6e585a43331d65e6077689abeacd7abafeabf4f6689c65cb56aacbff99b96be5d73606ab939e2bd06e8dfa058bd60731c5696c0f2fdf55dc5137086
data/CHANGELOG.md CHANGED
@@ -8,6 +8,11 @@
8
8
  ### Bug fixes
9
9
  )-->
10
10
 
11
+ ## 1.2.0 2025-04-10
12
+ - generate task can create an initializer that allows the generated stubs to work with zeitwerk
13
+ - added possibility to specify stubs path for generate task
14
+ - added possibility to specify stubs path for annotate task
15
+
11
16
  ## 1.1.3 2025-02-28
12
17
  - remove rails versions constraints, keep only dependency
13
18
 
data/README.md CHANGED
@@ -21,7 +21,7 @@ bundle
21
21
 
22
22
  ## Usage
23
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.
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` (or a path specified by the user), respecting the inner nesting. `annotate` annotates all the generated stubs with a comment section leveraging reflection.
25
25
 
26
26
  Beware that at the moment this gem does not support nested messages definition.
27
27
 
@@ -30,9 +30,15 @@ To generate the stubs simply run:
30
30
  ```bash
31
31
  rake grpc_stubs:generate
32
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.
33
+ The task accepts four optional positional arguments:
34
+ - `annotate` (default: `'yes'`): This specifies whether the task `annotate` should also be run. Options are `'yes'` and `'no'`
35
+ - `keep_require` (default: `'no'`): This specifies whether `generate` should remove all the `require ...` generated by `grpc_tools_ruby_protoc` or keep them. Options are `'yes'` and `'no'`
36
+ - `path` (default: `'app/stubs'`): This specifies the folder in which the stubs should be generated.
37
+ - `create_initializer` (default: `'yes'`): This specifies whether to create the file `config/initializers/protobuf_transpiler.rb`. Options are `'yes'` and `'no'`
38
+
39
+ 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).
40
+ 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.
41
+ To allow `zeitwerk` to work properly despite `grpc_tools_ruby_protoc` not respecting the naming conventions, by default the task will create an initializer that requires the generated stubs and stops the specified folder from being autoloaded (if it's inside of the `app` directory).
36
42
 
37
43
  For example if you have a gem defining proto files with this structure:
38
44
  ```
@@ -61,6 +67,9 @@ To annotate generated stubs simply run:
61
67
  ```bash
62
68
  rake grpc_stubs:annotate
63
69
  ```
70
+
71
+ This task has just one positional argument: `path`. It represents the folder in which the stubs were generated.
72
+
64
73
  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
74
 
66
75
  The annotations of messages follow these conventions:
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProtobufTranspiler
4
- VERSION = '1.1.3'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -7,26 +7,30 @@ module ProtobufTranspiler
7
7
  require_relative 'railtie'
8
8
 
9
9
  class << self
10
- def generate_stubs(keep_require = false)
10
+ def generate_stubs(keep_require = false, path = 'app/stubs')
11
11
  paths = $LOAD_PATH.map { |p| "#{p}/**/public/**/*.proto" }
12
12
  proto_files = Dir[*paths].join ' '
13
13
  proto_paths = proto_files
14
14
  .split.map { |p| p.sub %r{(?<=public).*}, '' }
15
15
  .uniq.join ' '
16
- out_path = "#{Rails.root}/app/stubs/"
16
+ out_path = "#{Rails.root}/#{path}/"
17
17
  FileUtils.mkdir_p out_path
18
18
  `grpc_tools_ruby_protoc --ruby_out=#{out_path} --grpc_out=#{out_path} #{proto_files} -I #{proto_paths}`
19
19
 
20
20
  # remove possibly useless require from stub file
21
21
  unless keep_require
22
- Dir['app/stubs/**/*.rb'].each do |fp|
22
+ Dir["#{path}/**/*.rb"].each do |fp|
23
23
  f = File.read fp
24
24
  File.write fp, (f.sub %r{\n(require.*?'\n)+}, '')
25
25
  end
26
26
  end
27
27
 
28
+ if path_in_app path
29
+ Rails.autoloaders.main.ignore "#{path}/**/*"
30
+ end
31
+
28
32
  # make zeitwerk happy
29
- Dir['app/stubs/**']
33
+ Dir["#{path}/**"]
30
34
  .filter { |f| File.directory? f }
31
35
  .each { |dir|
32
36
  requires = Dir.chdir dir do
@@ -37,15 +41,15 @@ module ProtobufTranspiler
37
41
  }
38
42
  end
39
43
 
40
- def annotate_stubs
44
+ def annotate_stubs path = 'app/stubs'
41
45
  require 'active_support/core_ext/string/inflections'
42
46
 
43
- Dir['app/stubs/**/*.rb']
47
+ Dir["#{path}/**/*.rb"]
44
48
  .map { |s| File.absolute_path s }
45
- .each { |f| require f }
49
+ .each { |f| zeitwerk_original_require f }
46
50
 
47
- stubs_modules = Dir['app/stubs/*.rb']
48
- .map { |s| s.sub('app/stubs/', '') }
51
+ stubs_modules = Dir["#{path}/*.rb"]
52
+ .map { |s| s.sub(path, '') }
49
53
  .map { |s| s.sub '.rb', '' }
50
54
  .uniq
51
55
  .map { |c| Object.const_get c.camelize }
@@ -54,7 +58,8 @@ module ProtobufTranspiler
54
58
  out = m
55
59
  .constants
56
60
  .sort
57
- .map { |c| m.const_get c }
61
+ .map { |c| ignore_errors(NameError) { m.const_get c } }
62
+ .filter(&:present?)
58
63
  .each_with_object({ messages: [], services: [] }) { |c, acc|
59
64
  if c.is_a? Class
60
65
  acc[:messages] << class_annotations(c)
@@ -62,7 +67,7 @@ module ProtobufTranspiler
62
67
  acc[:services] << module_annotations(c)
63
68
  end
64
69
  }
65
- types_file, services_file = Dir["app/stubs/#{m.name.underscore}/*.rb"]
70
+ types_file, services_file = Dir["#{path}/#{m.name.underscore}/*.rb"]
66
71
  .sort_by { |s| s.scan('services').count }
67
72
  [types_file, services_file]
68
73
  .zip([out[:messages], out[:services]])
@@ -70,10 +75,30 @@ module ProtobufTranspiler
70
75
  end
71
76
  end
72
77
 
78
+ def generate_initializer stubs_path = 'app/stubs'
79
+ file_content = ''
80
+
81
+ if path_in_app stubs_path
82
+ # Ignore the path in zeitwerk
83
+ file_content += "Rails.autoloaders.main.ignore '#{stubs_path}/**/*'\n"
84
+ end
85
+
86
+ file_content += "Dir[\"\#{Rails.root}/#{stubs_path}/*\"].each { |f| require_relative f }\n"
87
+
88
+ File.write "#{Rails.root}/config/initializers/protobuf_transpiler.rb", file_content
89
+ end
90
+
73
91
  private
74
92
 
75
93
  ANNOTATE_DELIMITER = '# ===== Protobuf Annotation ====='
76
94
 
95
+ def path_in_app path
96
+ stubs_path = File.realdirpath path, Rails.root
97
+ app_folder = File.realdirpath 'app', Rails.root
98
+
99
+ stubs_path.start_with? app_folder
100
+ end
101
+
77
102
  def class_annotations klass
78
103
  oneof_fields, oneof_annotations = lambda do |descriptor|
79
104
  [
@@ -124,13 +149,20 @@ module ProtobufTranspiler
124
149
  end.to_s
125
150
  end
126
151
 
152
+ def ignore_errors(*errors, &block)
153
+ begin
154
+ block.call
155
+ rescue errors
156
+ nil
157
+ end
158
+ end
159
+
127
160
  def module_annotations mod
128
- mod
129
- .const_get('Service')
130
- .rpc_descs.sort
131
- .map { |_, d| "\t#{d.name}(#{d.input}): #{d.output}" }
132
- .prepend(mod.name.to_s)
133
- .join "\n"
161
+ ignore_errors(NameError, NoMethodError) { mod.const_get('Service') }
162
+ &.sort
163
+ &.map { |_, d| "\t#{d.name}(#{d.input}): #{d.output}" }
164
+ &.prepend(mod.name.to_s)
165
+ &.join "\n"
134
166
  end
135
167
 
136
168
  def annotate_file file, content
@@ -1,16 +1,19 @@
1
1
  namespace :grpc_stubs do
2
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
3
+ task :generate, [:annotate, :keep_require, :path, :create_initializer] => :environment do |_, args|
4
+ args.with_defaults annotate: :yes, keep_require: :no, path: 'app/stubs', create_initializer: :yes
5
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
6
+ ProtobufTranspiler.generate_stubs args[:keep_require].to_sym == :yes, args[:path]
7
+ ProtobufTranspiler.generate_initializer args[:path] unless args[:create_initializer].to_sym == :no
8
+ ProtobufTranspiler.annotate_stubs args[:path] unless args[:annotate].to_sym == :no
8
9
  end
9
10
 
10
11
  desc 'Annotate generated stubs'
11
- task :annotate do
12
+ task :annotate, [:path, :create_initializer] => :environment do |_, args|
13
+ args.with_defaults path: 'app/stubs', create_initializer: :no
12
14
  require_relative '../protobuf_transpiler'
13
- ProtobufTranspiler.annotate_stubs
15
+ ProtobufTranspiler.generate_initializer args[:path] unless args[:create_initializer].to_sym == :no
16
+ ProtobufTranspiler.annotate_stubs args[:path]
14
17
  end
15
18
  end
16
19
 
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.1.3
4
+ version: 1.2.0
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: 2025-02-28 00:00:00.000000000 Z
12
+ date: 2025-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-protobuf
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
- rubygems_version: 3.4.6
117
+ rubygems_version: 3.5.22
118
118
  signing_key:
119
119
  specification_version: 4
120
120
  summary: A protobuf transpiler and annotator for Rails applications.