twirp_rails 0.3.2 → 0.4.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: '06560208f92156b0a681508de14468457ca498294e139f6f949f14f037ca03d4'
4
- data.tar.gz: '0989d1e84e085f7faaac0514c4140f96d3ffcf11f3bb157f1c775c38f06f83d3'
3
+ metadata.gz: 5dd3357733d9ed117fd486b9ef3dd7c4ca5bd9ffcb73a891e2959fb93aed2ec9
4
+ data.tar.gz: 1c5eee503666ad7810a9e02b0d3815d1716b8e9103799c9b1397a02bb95d78bb
5
5
  SHA512:
6
- metadata.gz: a56fe829dba492ce1df60576e045a254a2e116004065ce4d866d625d3717fefda40b48f5d31f5470c5b685f22ab2c3acf76232c6f91959823cf35c57906240ef
7
- data.tar.gz: dec12ac4cb49e5d6dca4f8460fa2029648e747b5ddba3653a44f09754dbcf27040cd02473279a11bb2e9a09bedd7bdaa8509f50a8a0926a4101b804ea97b863d
6
+ metadata.gz: ffc1c1b275fc2a92aab71d3c09371168abe9396123f31442e6f1352668523a8b8d4ca3cae3f224df0ac67942286ecc5ac0072524454f776f12a70704d1204a75
7
+ data.tar.gz: b54953adfc17d1b2d8fdce6af8e2e1d3f9be524b0f3917ddb80ed6e86f09cb4dc2235518aa03907c9a93fde188e35cf0bad7d7b47fab111d828ff63361069469
data/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 0.4.0 - 2020-03-24
8
+
9
+ ### Breaking changes
10
+
11
+ - Client and server proto directory splits from `app/protos` to `rpc` and `rpc/clients` (configurable)
12
+
13
+ ### Added
14
+
15
+ - Added gem configuration and generator to create initial configuration file `rails g twirp:init` (comments inside).
16
+ - Proto source dirs and rb destination dirs now configurable.
17
+ - Added separate generator to run protoc on clients proto files `rails g twirp:clients`.
18
+ - Add acronym API to Rails inflector to correct generate `ServiceAPI` handler from `ServiceApi` as protoc twirp plugin.
19
+ - In the development environment gem uses warn instead of raise errors on incorrect generated code or invalid service routes.
20
+
21
+ ### Fixed
22
+
23
+ - Fixed incorrect indent in generated modules.
24
+
7
25
  ## 0.3.2 - 2020-03-12
8
26
 
9
27
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- twirp_rails (0.3.2)
4
+ twirp_rails (0.4.0)
5
5
  railties (~> 6.0)
6
6
  twirp (~> 1)
7
7
 
@@ -16,7 +16,22 @@ module TwirpRails
16
16
  end
17
17
 
18
18
  initializer 'twirp_rails.require_generated_files' do
19
- TwirpRails::Twirp.auto_require_twirp_files
19
+ TwirpRails.handle_dev_error 'Require services twirp files' do
20
+ path = Pathname.new(TwirpRails.configuration.services_twirp_code_path)
21
+ path = Rails.root.join(path) if path.relative?
22
+ TwirpRails::Twirp.auto_require_twirp_files(path.to_s)
23
+ end
24
+ TwirpRails.handle_dev_error 'Require clients twirp files' do
25
+ path = Pathname.new(TwirpRails.configuration.clients_twirp_code_path)
26
+ path = Rails.root.join(path) if path.relative?
27
+ TwirpRails::Twirp.auto_require_twirp_files(path.to_s)
28
+ end
29
+ end
30
+
31
+ initializer 'twirp_rails.add_api_acronym' do
32
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
33
+ inflect.acronym 'API'
34
+ end
20
35
  end
21
36
  end
22
37
  end
@@ -0,0 +1,7 @@
1
+ Description:
2
+ Generate twirp code from protofiles of twirp_clients dir.
3
+
4
+ Example:
5
+ rails generate twirp:clients
6
+
7
+ This will run protoc generation on each file in the twirp_clients dir.
@@ -0,0 +1,51 @@
1
+ require 'rails/generators'
2
+
3
+ module Twirp
4
+ class ClientsGenerator < Rails::Generators::Base
5
+ desc 'This generator run protoc generation on each file in the twirp_clients dir'
6
+
7
+ def check_requirements
8
+ raise 'protoc not found - install protobuf (brew/apt/yum install protobuf)' unless File.exist?(TwirpGenerator::PROTOC_PATH)
9
+
10
+ unless File.exist?(TwirpGenerator::TWIRP_PLUGIN_PATH)
11
+ raise <<~TEXT
12
+ protoc-gen-twirp_ruby not found - install go (brew install go)
13
+ and run "go get github.com/twitchtv/twirp-ruby/protoc-gen-twirp_ruby
14
+ or set TWIRP_PLUGIN_PATH environment variable to right location.
15
+ TEXT
16
+ end
17
+ end
18
+
19
+ def generate_twirp_files
20
+ in_root do
21
+ FileUtils.mkdir_p cfg.clients_twirp_code_path
22
+
23
+ protos_mask = File.join cfg.clients_proto_path, '**/*.proto'
24
+ proto_files = Dir.glob protos_mask
25
+
26
+ proto_files.each do |file|
27
+ cmd = protoc_cmd(file)
28
+
29
+ `#{cmd}`
30
+
31
+ raise "protoc failure: #{cmd}" unless $?.success?
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def cfg
39
+ TwirpRails.configuration
40
+ end
41
+
42
+ def protoc_cmd(files)
43
+ flags = "--proto_path=#{cfg.clients_proto_path} " \
44
+ "--ruby_out=#{cfg.clients_twirp_code_path} --twirp_ruby_out=#{cfg.clients_twirp_code_path} " \
45
+ "--plugin=#{TwirpGenerator::TWIRP_PLUGIN_PATH}"
46
+
47
+ "#{TwirpGenerator::PROTOC_PATH} #{flags} #{files}"
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generate twirp_rails default initializer code.
3
+
4
+ Example:
5
+ rails generate twirp:init
6
+
7
+ This will create:
8
+ config/initializers/twirp_rails.rb
@@ -0,0 +1,12 @@
1
+ require 'rails/generators'
2
+
3
+ module Twirp
4
+ class InitGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('templates', __dir__)
6
+
7
+ desc 'This generator creates an initializer file at config/initializers'
8
+ def create_initializer_file
9
+ copy_file 'twirp_rails.rb', 'config/initializers/twirp_rails.rb'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ TwirpRails.configure do |config|
2
+ # Application services proto files path
3
+ # config.services_proto_path = 'rpc'
4
+ #
5
+ # Used clients proto files path
6
+ # config.clients_proto_path = 'rpc_clients'
7
+ #
8
+ # Services code generator destination path (autorequired on application start)
9
+ # config.services_twirp_code_path = 'lib/twirp'
10
+ #
11
+ # Clients code generator destination path (autorequired on application start)
12
+ # config.clients_twirp_code_path = 'lib/twirp_clients'
13
+ #
14
+ # Swagger files generated from services proto files path (set to nil unless you need to generete swagger)
15
+ # config.swagger_output_path = 'public/swagger'
16
+ #
17
+ # Instrument twirp calls and set hooks to log twirp calls
18
+ # set to proc to customize log output
19
+ # set to false to disable feature
20
+ # config.log_twirp_calls = true
21
+ end
@@ -4,7 +4,7 @@ class TwirpGenerator < Rails::Generators::NamedBase
4
4
  source_root File.expand_path('templates', __dir__)
5
5
 
6
6
  class_option :skip_swagger, type: :boolean, default: false
7
- class_option :swagger_out, type: :string, default: 'public/swagger'
7
+ class_option :swagger_out, type: :string, default: nil
8
8
 
9
9
  GOPATH = ENV.fetch('GOPATH') { File.expand_path('~/go') }
10
10
  GO_BIN_PATH = File.join(GOPATH, 'bin')
@@ -14,12 +14,12 @@ class TwirpGenerator < Rails::Generators::NamedBase
14
14
 
15
15
  def check_requirements
16
16
  in_root do
17
- unless File.exist?(proto_file_name)
18
- raise "#{proto_file_name} not found"
19
- end
17
+ raise "#{proto_file_name} not found" unless File.exist?(proto_file_name)
20
18
  end
21
19
 
22
- raise 'protoc not found - install protobuf (brew/apt/yum install protobuf)' unless File.exist?(PROTOC_PATH)
20
+ unless File.exist?(PROTOC_PATH)
21
+ raise 'protoc not found - install protobuf (brew/apt/yum install protobuf)'
22
+ end
23
23
 
24
24
  unless File.exist?(TWIRP_PLUGIN_PATH)
25
25
  raise <<~TEXT
@@ -40,12 +40,16 @@ class TwirpGenerator < Rails::Generators::NamedBase
40
40
 
41
41
  def generate_twirp_files
42
42
  in_root do
43
- protos_mask = File.join *['app/protos', class_path, '**/*.proto'].flatten
43
+ FileUtils.mkdir_p cfg.services_twirp_code_path
44
+
45
+ protos_mask = File.join cfg.services_proto_path, '**/*.proto'
44
46
  proto_files = Dir.glob protos_mask
45
47
 
46
48
  proto_files.each do |file|
47
49
  gen_swagger = gen_swagger? && file =~ %r{/#{file_name}\.proto$}
48
50
 
51
+ FileUtils.mkdir_p swagger_out_path if gen_swagger
52
+
49
53
  cmd = protoc_cmd(file, gen_swagger: gen_swagger)
50
54
 
51
55
  `#{cmd}`
@@ -63,7 +67,7 @@ class TwirpGenerator < Rails::Generators::NamedBase
63
67
  class_path.length.times do |i|
64
68
  current_path = class_path[0..i]
65
69
  create_file File.join('app/rpc', "#{current_path.join('/')}.rb"),
66
- module_hier(current_path.map(&:camelize), 0)
70
+ module_hier(current_path.map(&:camelize))
67
71
  end
68
72
  end
69
73
 
@@ -116,13 +120,13 @@ class TwirpGenerator < Rails::Generators::NamedBase
116
120
 
117
121
  private
118
122
 
119
- def module_hier(modules, indent)
123
+ def module_hier(modules, indent = 0)
120
124
  return '' if modules.size.zero?
121
125
 
122
126
  cur, *tail = modules
123
127
  optimize_indentation <<~RUBY, indent
124
128
  module #{cur}
125
- #{module_hier(tail, indent + 2)}end
129
+ #{module_hier(tail, 2)}end
126
130
  RUBY
127
131
  end
128
132
 
@@ -131,17 +135,13 @@ class TwirpGenerator < Rails::Generators::NamedBase
131
135
  end
132
136
 
133
137
  def protoc_cmd(files, gen_swagger: gen_swagger?)
134
- FileUtils.mkdir_p 'lib/twirp'
135
-
136
- flags = '--proto_path=app/protos ' \
137
- '--ruby_out=lib/twirp --twirp_ruby_out=lib/twirp ' \
138
+ flags = "--proto_path=#{cfg.services_proto_path} " \
139
+ "--ruby_out=#{cfg.services_twirp_code_path} --twirp_ruby_out=#{cfg.services_twirp_code_path} " \
138
140
  "--plugin=#{TWIRP_PLUGIN_PATH}"
139
141
 
140
142
  if gen_swagger
141
- FileUtils.mkdir_p options[:swagger_out]
142
-
143
143
  flags += " --plugin=#{SWAGGER_PLUGIN_PATH}" \
144
- " --twirp_swagger_out=#{options[:swagger_out]}"
144
+ " --twirp_swagger_out=#{swagger_out_path}"
145
145
  end
146
146
 
147
147
  "#{PROTOC_PATH} #{flags} #{files}"
@@ -157,10 +157,18 @@ class TwirpGenerator < Rails::Generators::NamedBase
157
157
  end
158
158
 
159
159
  def proto_file_name
160
- "app/protos/#{file_path}.proto"
160
+ File.join cfg.services_proto_path, "#{file_path}.proto"
161
+ end
162
+
163
+ def cfg
164
+ TwirpRails.configuration
161
165
  end
162
166
 
163
167
  def gen_swagger?
164
- !options[:skip_swagger]
168
+ !options[:skip_swagger] && cfg.swagger_output_path
169
+ end
170
+
171
+ def swagger_out_path
172
+ options[:swagger_out] || cfg.swagger_output_path
165
173
  end
166
174
  end
@@ -4,38 +4,37 @@ module TwirpRails
4
4
  module Routes # :nodoc:
5
5
  module Helper
6
6
  def mount_twirp(name, handler: nil, scope: 'twirp')
7
- case name
8
- when Class
9
- raise 'handler param required when name is a class' unless handler&.is_a?(Class)
7
+ TwirpRails.handle_dev_error "mount twirp route #{name}" do
8
+ case name
9
+ when Class
10
+ raise 'handler param required when name is a class' unless handler&.is_a?(Class)
10
11
 
11
- service_class = name
12
+ service_class = name
12
13
 
13
- when String, Symbol
14
- service_class = Helper.constantize_first "#{name}_service", name
14
+ when String, Symbol
15
+ service_class = Helper.constantize_first "#{name}_service", name
15
16
 
16
- unless service_class
17
- msg = "mount_twirp of #{name} error. #{name.camelize}Service or #{name.camelize} class is not found"
17
+ unless service_class
18
+ msg = "mount_twirp of #{name} error. #{name.camelize}Service or #{name.camelize} class is not found"
18
19
 
19
- raise TwirpRails::Error, msg unless Rails.env.development?
20
+ raise TwirpRails::Error, msg
21
+ end
20
22
 
21
- warn msg
22
- return
23
+ handler ||= "#{name}_handler".camelize.constantize
24
+ else
25
+ raise 'twirp service name required'
23
26
  end
24
27
 
25
- handler ||= "#{name}_handler".camelize.constantize
26
- else
27
- raise 'twirp service name required'
28
- end
29
-
30
- service = service_class.new(handler.new)
31
- Helper.run_create_hooks service
28
+ service = service_class.new(handler.new)
29
+ Helper.run_create_hooks service
32
30
 
33
- if scope
34
- scope scope do
31
+ if scope
32
+ scope scope do
33
+ mount service, at: service.full_name
34
+ end
35
+ else
35
36
  mount service, at: service.full_name
36
37
  end
37
- else
38
- mount service, at: service.full_name
39
38
  end
40
39
  end
41
40
 
@@ -1,9 +1,8 @@
1
1
  module TwirpRails
2
2
  module Twirp
3
- def self.auto_require_twirp_files
3
+ def self.auto_require_twirp_files(twirp_path)
4
4
  # protoc generates require without path in a _pb files
5
- twirp_path = Rails.root.join('lib/twirp').to_s
6
- $LOAD_PATH.unshift(twirp_path) if !$LOAD_PATH.include?(twirp_path)
5
+ $LOAD_PATH.unshift(twirp_path) unless $LOAD_PATH.include?(twirp_path)
7
6
 
8
7
  Dir.glob(Rails.root.join('lib/twirp/**/*_twirp.rb')).sort.each do |file|
9
8
  require file
@@ -1,3 +1,3 @@
1
1
  module TwirpRails
2
- VERSION = '0.3.2'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
data/lib/twirp_rails.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'twirp_rails/version'
4
4
  require 'twirp_rails/engine'
5
+ require 'twirp_rails/generators/twirp/init/init_generator'
6
+ require 'twirp_rails/generators/twirp/clients/clients_generator'
5
7
  require 'twirp_rails/generators/twirp/twirp_generator'
6
8
  require 'twirp_rails/generators/twirp/twirp_rspec_generator'
7
9
  require 'twirp_rails/active_record_extension'
@@ -10,10 +12,92 @@ require 'twirp_rails/log_subscriber'
10
12
  module TwirpRails
11
13
  class Error < StandardError; end
12
14
 
15
+ class Configuration
16
+ def self.config_param(symbol, default_value = nil, &block)
17
+ raise 'wrong args' if !default_value.nil? && block_given?
18
+
19
+ if block_given?
20
+ class_variable_set("@@#{symbol}_default", block)
21
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
22
+ def #{symbol}_default
23
+ instance_eval &@@#{symbol}_default
24
+ end
25
+ RUBY
26
+ else
27
+ class_variable_set("@@#{symbol}_default", default_value)
28
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
29
+ def #{symbol}_default
30
+ @@#{symbol}_default
31
+ end
32
+ RUBY
33
+ end
34
+
35
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
36
+ def #{symbol}
37
+ @#{symbol} ||= #{symbol}_default
38
+ end
39
+ RUBY
40
+
41
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
42
+ def #{symbol}?
43
+ #{symbol}
44
+ end
45
+
46
+ def #{symbol}=(value)
47
+ @#{symbol} = value
48
+ end
49
+ RUBY
50
+ end
51
+
52
+ config_param :services_proto_path, 'rpc'
53
+
54
+ config_param :clients_proto_path, 'rpc_clients'
55
+
56
+ config_param :services_twirp_code_path, 'lib/twirp'
57
+
58
+ config_param :clients_twirp_code_path, 'lib/twirp_clients'
59
+
60
+ config_param :swagger_output_path, 'public/swagger'
61
+
62
+ config_param :log_twirp_calls, true
63
+ end
64
+
65
+ def self.configuration
66
+ @configuration ||= Configuration.new
67
+ end
68
+
69
+ def self.configure
70
+ yield configuration if block_given?
71
+ setup
72
+ end
73
+
74
+ def self.setup
75
+ if configuration.log_twirp_calls
76
+ if configuration.log_twirp_calls.is_a?(Proc)
77
+ log_twirp_calls!(&configuration.log_twirp_calls)
78
+ else
79
+ log_twirp_calls!
80
+ end
81
+ end
82
+ end
83
+
13
84
  def self.log_twirp_calls!(&log_writer)
14
85
  TwirpRails::LoggingAdapter.install
15
86
 
16
87
  TwirpRails::LogSubscriber.log_writer = log_writer if block_given?
17
88
  TwirpRails::LogSubscriber.attach_to(:twirp)
18
89
  end
90
+
91
+ def self.handle_dev_error(msg, &_)
92
+ if Rails.env.development? && !ENV['TWIRP_RAILS_RAISE']
93
+ begin
94
+ yield
95
+ rescue StandardError => e
96
+ warn("#{msg} #{e.message}")
97
+ warn('twirp_rails error raised but control flow will resume for development environment. Define env TWIRP_RAILS_RAISE to raise error.')
98
+ end
99
+ else
100
+ yield
101
+ end
102
+ end
19
103
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twirp_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandr Zimin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-12 00:00:00.000000000 Z
11
+ date: 2020-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: twirp
@@ -143,6 +143,11 @@ files:
143
143
  - lib/twirp_rails/active_record_extension.rb
144
144
  - lib/twirp_rails/engine.rb
145
145
  - lib/twirp_rails/generators/twirp/USAGE
146
+ - lib/twirp_rails/generators/twirp/clients/USAGE
147
+ - lib/twirp_rails/generators/twirp/clients/clients_generator.rb
148
+ - lib/twirp_rails/generators/twirp/init/USAGE
149
+ - lib/twirp_rails/generators/twirp/init/init_generator.rb
150
+ - lib/twirp_rails/generators/twirp/init/templates/twirp_rails.rb
146
151
  - lib/twirp_rails/generators/twirp/twirp_generator.rb
147
152
  - lib/twirp_rails/generators/twirp/twirp_rspec_generator.rb
148
153
  - lib/twirp_rails/log_subscriber.rb