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 +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
|