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 +4 -4
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +1 -1
- data/lib/twirp_rails/engine.rb +16 -1
- data/lib/twirp_rails/generators/twirp/clients/USAGE +7 -0
- data/lib/twirp_rails/generators/twirp/clients/clients_generator.rb +51 -0
- data/lib/twirp_rails/generators/twirp/init/USAGE +8 -0
- data/lib/twirp_rails/generators/twirp/init/init_generator.rb +12 -0
- data/lib/twirp_rails/generators/twirp/init/templates/twirp_rails.rb +21 -0
- data/lib/twirp_rails/generators/twirp/twirp_generator.rb +26 -18
- data/lib/twirp_rails/routes.rb +21 -22
- data/lib/twirp_rails/twirp.rb +2 -3
- data/lib/twirp_rails/version.rb +1 -1
- data/lib/twirp_rails.rb +84 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dd3357733d9ed117fd486b9ef3dd7c4ca5bd9ffcb73a891e2959fb93aed2ec9
|
4
|
+
data.tar.gz: 1c5eee503666ad7810a9e02b0d3815d1716b8e9103799c9b1397a02bb95d78bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/lib/twirp_rails/engine.rb
CHANGED
@@ -16,7 +16,22 @@ module TwirpRails
|
|
16
16
|
end
|
17
17
|
|
18
18
|
initializer 'twirp_rails.require_generated_files' do
|
19
|
-
TwirpRails
|
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,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,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:
|
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
|
-
|
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
|
-
|
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)
|
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,
|
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
|
-
|
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=#{
|
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
|
-
"
|
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
|
data/lib/twirp_rails/routes.rb
CHANGED
@@ -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
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
12
|
+
service_class = name
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
when String, Symbol
|
15
|
+
service_class = Helper.constantize_first "#{name}_service", name
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
unless service_class
|
18
|
+
msg = "mount_twirp of #{name} error. #{name.camelize}Service or #{name.camelize} class is not found"
|
18
19
|
|
19
|
-
|
20
|
+
raise TwirpRails::Error, msg
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
+
handler ||= "#{name}_handler".camelize.constantize
|
24
|
+
else
|
25
|
+
raise 'twirp service name required'
|
23
26
|
end
|
24
27
|
|
25
|
-
|
26
|
-
|
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
|
-
|
34
|
-
|
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
|
|
data/lib/twirp_rails/twirp.rb
CHANGED
@@ -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
|
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
|
data/lib/twirp_rails/version.rb
CHANGED
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.
|
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-
|
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
|