twirp_rails 0.3.2 → 0.4.0

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: '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