twirbet 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +20 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Gemfile +28 -0
  6. data/Gemfile.lock +127 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +144 -0
  9. data/Rakefile +17 -0
  10. data/examples/clientcompat/client +28 -0
  11. data/examples/clientcompat/clientcompat.proto +29 -0
  12. data/examples/clientcompat/clientcompat_pb.rb +36 -0
  13. data/examples/clientcompat/clientcompat_twirbet.rb +57 -0
  14. data/examples/ping/Gemfile +11 -0
  15. data/examples/ping/Gemfile.lock +69 -0
  16. data/examples/ping/bin/puma +27 -0
  17. data/examples/ping/bin/pumactl +27 -0
  18. data/examples/ping/bin/srb +27 -0
  19. data/examples/ping/bin/srb-rbi +27 -0
  20. data/examples/ping/bin/tapioca +27 -0
  21. data/examples/ping/client.rb +14 -0
  22. data/examples/ping/config/application.rb +13 -0
  23. data/examples/ping/config/environment.rb +6 -0
  24. data/examples/ping/config.ru +8 -0
  25. data/examples/ping/proto/ping.proto +15 -0
  26. data/examples/ping/proto/ping_pb.rb +20 -0
  27. data/examples/ping/proto/ping_twirbet.rb +47 -0
  28. data/examples/ping/sorbet/config +4 -0
  29. data/examples/ping/sorbet/rbi/dsl/google/protobuf/descriptor_proto/extension_range.rbi +34 -0
  30. data/examples/ping/sorbet/rbi/dsl/google/protobuf/descriptor_proto/reserved_range.rbi +22 -0
  31. data/examples/ping/sorbet/rbi/dsl/google/protobuf/descriptor_proto.rbi +83 -0
  32. data/examples/ping/sorbet/rbi/dsl/google/protobuf/enum_descriptor_proto/enum_reserved_range.rbi +22 -0
  33. data/examples/ping/sorbet/rbi/dsl/google/protobuf/enum_descriptor_proto.rbi +48 -0
  34. data/examples/ping/sorbet/rbi/dsl/google/protobuf/enum_options.rbi +34 -0
  35. data/examples/ping/sorbet/rbi/dsl/google/protobuf/enum_value_descriptor_proto.rbi +34 -0
  36. data/examples/ping/sorbet/rbi/dsl/google/protobuf/enum_value_options.rbi +27 -0
  37. data/examples/ping/sorbet/rbi/dsl/google/protobuf/extension_range_options.rbi +20 -0
  38. data/examples/ping/sorbet/rbi/dsl/google/protobuf/field_descriptor_proto/label.rbi +22 -0
  39. data/examples/ping/sorbet/rbi/dsl/google/protobuf/field_descriptor_proto/type.rbi +37 -0
  40. data/examples/ping/sorbet/rbi/dsl/google/protobuf/field_descriptor_proto.rbi +90 -0
  41. data/examples/ping/sorbet/rbi/dsl/google/protobuf/field_options/c_type.rbi +22 -0
  42. data/examples/ping/sorbet/rbi/dsl/google/protobuf/field_options/js_type.rbi +22 -0
  43. data/examples/ping/sorbet/rbi/dsl/google/protobuf/field_options.rbi +69 -0
  44. data/examples/ping/sorbet/rbi/dsl/google/protobuf/file_descriptor_proto.rbi +97 -0
  45. data/examples/ping/sorbet/rbi/dsl/google/protobuf/file_descriptor_set.rbi +20 -0
  46. data/examples/ping/sorbet/rbi/dsl/google/protobuf/file_options/optimize_mode.rbi +22 -0
  47. data/examples/ping/sorbet/rbi/dsl/google/protobuf/file_options.rbi +160 -0
  48. data/examples/ping/sorbet/rbi/dsl/google/protobuf/generated_code_info/annotation.rbi +41 -0
  49. data/examples/ping/sorbet/rbi/dsl/google/protobuf/generated_code_info.rbi +20 -0
  50. data/examples/ping/sorbet/rbi/dsl/google/protobuf/map.rbi +12 -0
  51. data/examples/ping/sorbet/rbi/dsl/google/protobuf/message_options.rbi +48 -0
  52. data/examples/ping/sorbet/rbi/dsl/google/protobuf/method_descriptor_proto.rbi +55 -0
  53. data/examples/ping/sorbet/rbi/dsl/google/protobuf/method_options/idempotency_level.rbi +22 -0
  54. data/examples/ping/sorbet/rbi/dsl/google/protobuf/method_options.rbi +34 -0
  55. data/examples/ping/sorbet/rbi/dsl/google/protobuf/oneof_descriptor_proto.rbi +22 -0
  56. data/examples/ping/sorbet/rbi/dsl/google/protobuf/oneof_options.rbi +20 -0
  57. data/examples/ping/sorbet/rbi/dsl/google/protobuf/repeated_field.rbi +11 -0
  58. data/examples/ping/sorbet/rbi/dsl/google/protobuf/service_descriptor_proto.rbi +34 -0
  59. data/examples/ping/sorbet/rbi/dsl/google/protobuf/service_options.rbi +27 -0
  60. data/examples/ping/sorbet/rbi/dsl/google/protobuf/source_code_info/location.rbi +48 -0
  61. data/examples/ping/sorbet/rbi/dsl/google/protobuf/source_code_info.rbi +20 -0
  62. data/examples/ping/sorbet/rbi/dsl/google/protobuf/uninterpreted_option/name_part.rbi +22 -0
  63. data/examples/ping/sorbet/rbi/dsl/google/protobuf/uninterpreted_option.rbi +62 -0
  64. data/examples/ping/sorbet/rbi/dsl/ping/ping_request.rbi +16 -0
  65. data/examples/ping/sorbet/rbi/dsl/ping/ping_response.rbi +16 -0
  66. data/examples/ping/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  67. data/examples/ping/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +8 -0
  68. data/examples/ping/sorbet/rbi/gems/google-protobuf@3.21.12.rbi +1645 -0
  69. data/examples/ping/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  70. data/examples/ping/sorbet/rbi/gems/nio4r@2.5.8.rbi +8 -0
  71. data/examples/ping/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
  72. data/examples/ping/sorbet/rbi/gems/parser@3.1.3.0.rbi +5076 -0
  73. data/examples/ping/sorbet/rbi/gems/puma@6.0.0.rbi +4177 -0
  74. data/examples/ping/sorbet/rbi/gems/rack@3.0.2.rbi +5016 -0
  75. data/examples/ping/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
  76. data/examples/ping/sorbet/rbi/gems/spoom@1.1.15.rbi +2383 -0
  77. data/examples/ping/sorbet/rbi/gems/tapioca@0.10.3.rbi +3032 -0
  78. data/examples/ping/sorbet/rbi/gems/thor@1.2.1.rbi +3919 -0
  79. data/examples/ping/sorbet/rbi/gems/twirbet@0.1.0.rbi +528 -0
  80. data/examples/ping/sorbet/rbi/gems/unparser@0.6.5.rbi +8 -0
  81. data/examples/ping/sorbet/rbi/gems/webrick@1.7.0.rbi +2498 -0
  82. data/examples/ping/sorbet/rbi/gems/yard-sorbet@0.7.0.rbi +391 -0
  83. data/examples/ping/sorbet/rbi/gems/yard@0.9.28.rbi +17022 -0
  84. data/examples/ping/sorbet/tapioca/config.yml +13 -0
  85. data/examples/ping/sorbet/tapioca/require.rb +5 -0
  86. data/lib/twirbet/client.rb +45 -0
  87. data/lib/twirbet/dsl.rb +84 -0
  88. data/lib/twirbet/encoding.rb +52 -0
  89. data/lib/twirbet/errors.rb +375 -0
  90. data/lib/twirbet/method.rb +34 -0
  91. data/lib/twirbet/service.rb +85 -0
  92. data/lib/twirbet/transport.rb +55 -0
  93. data/lib/twirbet/transports/fake_transport.rb +32 -0
  94. data/lib/twirbet/transports/net_http_transport.rb +20 -0
  95. data/lib/twirbet/version.rb +6 -0
  96. data/lib/twirbet.rb +11 -0
  97. data/sorbet/config +5 -0
  98. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  99. data/sorbet/rbi/custom/ping.rbi +23 -0
  100. data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
  101. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1064 -0
  102. data/sorbet/rbi/gems/google-protobuf@3.21.12.rbi +1645 -0
  103. data/sorbet/rbi/gems/json@2.6.3.rbi +1541 -0
  104. data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
  105. data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
  106. data/sorbet/rbi/gems/parser@3.1.3.0.rbi +6878 -0
  107. data/sorbet/rbi/gems/rack@3.0.2.rbi +5163 -0
  108. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +397 -0
  109. data/sorbet/rbi/gems/rake@13.0.6.rbi +2946 -0
  110. data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
  111. data/sorbet/rbi/gems/regexp_parser@2.6.1.rbi +3126 -0
  112. data/sorbet/rbi/gems/rexml@3.2.5.rbi +4660 -0
  113. data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10492 -0
  114. data/sorbet/rbi/gems/rspec-expectations@3.12.1.rbi +7817 -0
  115. data/sorbet/rbi/gems/rspec-mocks@3.12.1.rbi +4994 -0
  116. data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1477 -0
  117. data/sorbet/rbi/gems/rspec@3.12.0.rbi +10 -0
  118. data/sorbet/rbi/gems/rubocop-ast@1.24.0.rbi +6790 -0
  119. data/sorbet/rbi/gems/rubocop-rake@0.6.0.rbi +354 -0
  120. data/sorbet/rbi/gems/rubocop-rspec@2.16.0.rbi +7650 -0
  121. data/sorbet/rbi/gems/rubocop-shopify@2.10.1.rbi +8 -0
  122. data/sorbet/rbi/gems/rubocop-sorbet@0.6.11.rbi +1014 -0
  123. data/sorbet/rbi/gems/rubocop@1.40.0.rbi +51560 -0
  124. data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +1212 -0
  125. data/sorbet/rbi/gems/spoom@1.1.15.rbi +2383 -0
  126. data/sorbet/rbi/gems/tapioca@0.10.3.rbi +3032 -0
  127. data/sorbet/rbi/gems/thor@1.2.1.rbi +3950 -0
  128. data/sorbet/rbi/gems/unicode-display_width@2.3.0.rbi +46 -0
  129. data/sorbet/rbi/gems/unparser@0.6.5.rbi +4265 -0
  130. data/sorbet/rbi/gems/webrick@1.7.0.rbi +2498 -0
  131. data/sorbet/rbi/gems/yard-sorbet@0.7.0.rbi +391 -0
  132. data/sorbet/rbi/gems/yard@0.9.28.rbi +17033 -0
  133. data/sorbet/tapioca/config.yml +13 -0
  134. data/sorbet/tapioca/require.rb +4 -0
  135. data/twirbet.gemspec +36 -0
  136. metadata +223 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8e9eb1c622bae0eec82613b9cc851082c98ec12c11cd6c06cae9d39cc14da87f
4
+ data.tar.gz: 80003e80a7c9e38529805adbb2b87edcb2c47e9e5244258bb72e5dd8839321a4
5
+ SHA512:
6
+ metadata.gz: 74eb8e008aae34d7757b82bc4e031f172deba804a088abfa4f306d30eb319f4e730f6234b4bc33c8cc557042e05eda97e5c3fffcca842181c7876b966f40b60b
7
+ data.tar.gz: 5da000d1fac1baec0d690c974eaca37711176b6c511cddea000e975c7da0dfabb6a0ee079a8db29dacd0b0ff7ff36285fe7bbf984a5fab5950a5c7e7d45fb1d6
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,20 @@
1
+ require:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+ - rubocop-sorbet
5
+
6
+ inherit_gem:
7
+ rubocop-shopify: rubocop.yml
8
+
9
+ AllCops:
10
+ NewCops: enable
11
+ Exclude:
12
+ - examples/**/*
13
+
14
+ Sorbet/ValidSigil:
15
+ Exclude:
16
+ - ./**/*_pb.rb
17
+
18
+ Sorbet/FalseSigil:
19
+ Exclude:
20
+ - ./**/*_pb.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-12-18
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in twirbet.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "rubocop", "~> 1.21"
13
+
14
+ gem "rubocop-rake", "~> 0.6.0"
15
+
16
+ gem "rubocop-rspec", "~> 2.16"
17
+
18
+ gem "rubocop-shopify", "~> 2.10"
19
+
20
+ gem "rubocop-sorbet", "~> 0.6.11"
21
+
22
+ gem "sorbet", "~> 0.5.10595"
23
+
24
+ gem "spoom", "~> 1.1"
25
+
26
+ gem "tapioca", "~> 0.10.3"
27
+
28
+ gem "webmock", "~> 3.18"
data/Gemfile.lock ADDED
@@ -0,0 +1,127 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ twirbet (0.1.0)
5
+ google-protobuf (~> 3.21)
6
+ rack (~> 3.0)
7
+ sorbet-runtime (~> 0.5.10595)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.8.1)
13
+ public_suffix (>= 2.0.2, < 6.0)
14
+ ast (2.4.2)
15
+ crack (0.4.5)
16
+ rexml
17
+ diff-lcs (1.5.0)
18
+ google-protobuf (3.21.12)
19
+ google-protobuf (3.21.12-x86_64-linux)
20
+ hashdiff (1.0.1)
21
+ json (2.6.3)
22
+ netrc (0.11.0)
23
+ parallel (1.22.1)
24
+ parser (3.1.3.0)
25
+ ast (~> 2.4.1)
26
+ public_suffix (5.0.1)
27
+ rack (3.0.2)
28
+ rainbow (3.1.1)
29
+ rake (13.0.6)
30
+ rbi (0.0.16)
31
+ ast
32
+ parser (>= 2.6.4.0)
33
+ sorbet-runtime (>= 0.5.9204)
34
+ unparser
35
+ regexp_parser (2.6.1)
36
+ rexml (3.2.5)
37
+ rspec (3.12.0)
38
+ rspec-core (~> 3.12.0)
39
+ rspec-expectations (~> 3.12.0)
40
+ rspec-mocks (~> 3.12.0)
41
+ rspec-core (3.12.0)
42
+ rspec-support (~> 3.12.0)
43
+ rspec-expectations (3.12.1)
44
+ diff-lcs (>= 1.2.0, < 2.0)
45
+ rspec-support (~> 3.12.0)
46
+ rspec-mocks (3.12.1)
47
+ diff-lcs (>= 1.2.0, < 2.0)
48
+ rspec-support (~> 3.12.0)
49
+ rspec-support (3.12.0)
50
+ rubocop (1.40.0)
51
+ json (~> 2.3)
52
+ parallel (~> 1.10)
53
+ parser (>= 3.1.2.1)
54
+ rainbow (>= 2.2.2, < 4.0)
55
+ regexp_parser (>= 1.8, < 3.0)
56
+ rexml (>= 3.2.5, < 4.0)
57
+ rubocop-ast (>= 1.23.0, < 2.0)
58
+ ruby-progressbar (~> 1.7)
59
+ unicode-display_width (>= 1.4.0, < 3.0)
60
+ rubocop-ast (1.24.0)
61
+ parser (>= 3.1.1.0)
62
+ rubocop-rake (0.6.0)
63
+ rubocop (~> 1.0)
64
+ rubocop-rspec (2.16.0)
65
+ rubocop (~> 1.33)
66
+ rubocop-shopify (2.10.1)
67
+ rubocop (~> 1.35)
68
+ rubocop-sorbet (0.6.11)
69
+ rubocop (>= 0.90.0)
70
+ ruby-progressbar (1.11.0)
71
+ sorbet (0.5.10595)
72
+ sorbet-static (= 0.5.10595)
73
+ sorbet-runtime (0.5.10595)
74
+ sorbet-static (0.5.10595-universal-darwin-21)
75
+ sorbet-static (0.5.10595-x86_64-linux)
76
+ sorbet-static-and-runtime (0.5.10595)
77
+ sorbet (= 0.5.10595)
78
+ sorbet-runtime (= 0.5.10595)
79
+ spoom (1.1.15)
80
+ sorbet (>= 0.5.10187)
81
+ sorbet-runtime (>= 0.5.9204)
82
+ thor (>= 0.19.2)
83
+ tapioca (0.10.3)
84
+ bundler (>= 1.17.3)
85
+ netrc (>= 0.11.0)
86
+ parallel (>= 1.21.0)
87
+ rbi (~> 0.0.0, >= 0.0.16)
88
+ sorbet-static-and-runtime (>= 0.5.9892)
89
+ spoom (~> 1.1.0, >= 1.1.11)
90
+ thor (>= 1.2.0)
91
+ yard-sorbet
92
+ thor (1.2.1)
93
+ unicode-display_width (2.3.0)
94
+ unparser (0.6.5)
95
+ diff-lcs (~> 1.3)
96
+ parser (>= 3.1.0)
97
+ webmock (3.18.1)
98
+ addressable (>= 2.8.0)
99
+ crack (>= 0.3.2)
100
+ hashdiff (>= 0.4.0, < 2.0.0)
101
+ webrick (1.7.0)
102
+ yard (0.9.28)
103
+ webrick (~> 1.7.0)
104
+ yard-sorbet (0.7.0)
105
+ sorbet-runtime (>= 0.5)
106
+ yard (>= 0.9)
107
+
108
+ PLATFORMS
109
+ arm64-darwin-21
110
+ x86_64-linux
111
+
112
+ DEPENDENCIES
113
+ rake (~> 13.0)
114
+ rspec (~> 3.0)
115
+ rubocop (~> 1.21)
116
+ rubocop-rake (~> 0.6.0)
117
+ rubocop-rspec (~> 2.16)
118
+ rubocop-shopify (~> 2.10)
119
+ rubocop-sorbet (~> 0.6.11)
120
+ sorbet (~> 0.5.10595)
121
+ spoom (~> 1.1)
122
+ tapioca (~> 0.10.3)
123
+ twirbet!
124
+ webmock (~> 3.18)
125
+
126
+ BUNDLED WITH
127
+ 2.3.26
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Brave Hager
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Twirbet
2
+
3
+ Twirbet is a Sorbet-friendly Ruby library for the Twirp RPC framework.
4
+
5
+ ## Installation
6
+
7
+ Twirbet is available as a Ruby gem. To install it via Bundler, run:
8
+
9
+ ```sh
10
+ bundle install twirbet
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Defining a service
16
+
17
+ Twirbet does not provide code generation (yet).
18
+
19
+ You can use the `Twirbet::Service` and `Twirbet::Client` classes to implement
20
+ and call Twirp services.
21
+
22
+ Given a service defined in `ping.proto`:
23
+
24
+ ```protobuf
25
+ syntax = "proto3";
26
+
27
+ service PingService {
28
+ rpc Ping(PingRequest) returns (PingResponse);
29
+ }
30
+
31
+ message PingRequest {
32
+ string message = 1;
33
+ }
34
+
35
+ message PingResponse {
36
+ string message = 1;
37
+ }
38
+ ```
39
+
40
+ Here's the corresponding Ruby code:
41
+
42
+ ```ruby
43
+ require "twirbet"
44
+ require_relative "ping_pb"
45
+
46
+ module PingService
47
+ module Handler
48
+ extend T::Sig
49
+ extend T::Helpers
50
+
51
+ interface!
52
+
53
+ sig { abstract.params(request: PingRequest).returns(PingResponse) }
54
+ def ping(request); end
55
+ end
56
+
57
+ class Service < Twirbet::Service
58
+ extend T::Sig
59
+
60
+ service "PingService"
61
+
62
+ rpc "Ping", PingRequest, PingResponse, ruby_method: :ping
63
+
64
+ sig { params(handler: Handler).void }
65
+ def initialize(handler)
66
+ super(handler)
67
+ end
68
+ end
69
+
70
+ class Client < Twirbet::Client
71
+ extend T::Sig
72
+ include Handler
73
+
74
+ service "PingService"
75
+
76
+ rpc "Ping", PingRequest, PingResponse, ruby_method: :ping
77
+
78
+ sig { override.params(request: PingRequest, headers: T::Hash[String, String]).returns(PingResponse) }
79
+ def ping(request, headers = {})
80
+ call("Ping", request, headers)
81
+ end
82
+ end
83
+ end
84
+ ```
85
+
86
+ ### Implementing a service
87
+
88
+ Once you have defined a service, you can implement it by creating a class that
89
+ includes the `Handler` interface:
90
+
91
+ ```ruby
92
+ class PingHandler
93
+ include PingService::Handler
94
+
95
+ sig { override.params(request: PingRequest).returns(PingResponse) }
96
+ def ping(request)
97
+ PingResponse.new(message: "Pong: #{request.message}")
98
+ end
99
+ end
100
+ ```
101
+
102
+ ### Starting a server
103
+
104
+ All services are valid Rack applications. You can use any Rack server to start a
105
+ Twirp server.
106
+
107
+ ```ruby
108
+ handler = PingHandler.new
109
+ service = PingService::Service.new(handler)
110
+
111
+ run service
112
+ ```
113
+
114
+ ### Calling a service
115
+
116
+ You can call a service using the client:
117
+
118
+ ```ruby
119
+ client = PingService::Client.new("http://localhost:8080")
120
+
121
+ response = client.ping(PingRequest.new(message: "Hello, world!"))
122
+
123
+ puts response.message # => "Pong: Hello, world!"
124
+ ```
125
+
126
+ ### Using a different HTTP client library
127
+
128
+ Twirbet uses the built-in `Net::HTTP` library to make HTTP requests. You can use
129
+ a different HTTP library by implementing the `Twirbet::Transport` interface and
130
+ passing it to the client constructor:
131
+
132
+ For example, Twirbet provides a `Twirbet::Transports::FakeTransport` class that
133
+ can be used for testing:
134
+
135
+ ```ruby
136
+ require "twirbet/transports/fake_transport"
137
+
138
+ transport = Twirbet::Transports::FakeTransport.new
139
+ client = PingService::Client.new("http://localhost:8080", transport: transport)
140
+
141
+ response = client.ping(PingRequest.new(message: "Hello, world!"))
142
+
143
+ puts response.message # => ""
144
+ ```
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: [:spec, :rubocop]
13
+
14
+ desc "Run client compatibility tests"
15
+ task clientcompat: ["install:local"] do
16
+ sh "clientcompat -client=examples/clientcompat/client"
17
+ end
@@ -0,0 +1,28 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require_relative "clientcompat_twirbet"
4
+
5
+ message = Twirp::Clientcompat::ClientCompatMessage.decode(STDIN.read)
6
+
7
+ client = Twirp::Clientcompat::CompatService::Client.new(message.service_address)
8
+
9
+ case message.method_name
10
+ when :NOOP
11
+ request = Google::Protobuf.decode(Twirp::Clientcompat::Empty, message.request)
12
+ begin
13
+ response = client.noop_method(request)
14
+ $stdout.write(response.to_proto)
15
+ rescue Twirbet::BaseError => e
16
+ $stderr.write(e.code)
17
+ end
18
+ when :METHOD
19
+ request = Google::Protobuf.decode(Twirp::Clientcompat::Req, message.request)
20
+ begin
21
+ response = client.real_method(request)
22
+ $stdout.write(response.to_proto)
23
+ rescue Twirbet::BaseError => e
24
+ $stderr.write(e.code)
25
+ end
26
+ else
27
+ raise "Unknown method: #{message.method_name}"
28
+ end
@@ -0,0 +1,29 @@
1
+ syntax = "proto3";
2
+
3
+ package twirp.clientcompat;
4
+ option go_package = "/internal/clientcompat";
5
+
6
+ service CompatService {
7
+ rpc Method(Req) returns (Resp);
8
+ rpc NoopMethod(Empty) returns (Empty);
9
+ }
10
+
11
+ message Empty {}
12
+
13
+ message Req {
14
+ string v = 1;
15
+ }
16
+
17
+ message Resp {
18
+ int32 v = 1;
19
+ }
20
+
21
+ message ClientCompatMessage {
22
+ string service_address = 1;
23
+ enum CompatServiceMethod {
24
+ NOOP = 0;
25
+ METHOD = 1;
26
+ }
27
+ CompatServiceMethod method_name = 2;
28
+ bytes request = 3;
29
+ }
@@ -0,0 +1,36 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: clientcompat.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("clientcompat.proto", :syntax => :proto3) do
8
+ add_message "twirp.clientcompat.Empty" do
9
+ end
10
+ add_message "twirp.clientcompat.Req" do
11
+ optional :v, :string, 1
12
+ end
13
+ add_message "twirp.clientcompat.Resp" do
14
+ optional :v, :int32, 1
15
+ end
16
+ add_message "twirp.clientcompat.ClientCompatMessage" do
17
+ optional :service_address, :string, 1
18
+ optional :method_name, :enum, 2, "twirp.clientcompat.ClientCompatMessage.CompatServiceMethod"
19
+ optional :request, :bytes, 3
20
+ end
21
+ add_enum "twirp.clientcompat.ClientCompatMessage.CompatServiceMethod" do
22
+ value :NOOP, 0
23
+ value :METHOD, 1
24
+ end
25
+ end
26
+ end
27
+
28
+ module Twirp
29
+ module Clientcompat
30
+ Empty = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("twirp.clientcompat.Empty").msgclass
31
+ Req = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("twirp.clientcompat.Req").msgclass
32
+ Resp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("twirp.clientcompat.Resp").msgclass
33
+ ClientCompatMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("twirp.clientcompat.ClientCompatMessage").msgclass
34
+ ClientCompatMessage::CompatServiceMethod = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("twirp.clientcompat.ClientCompatMessage.CompatServiceMethod").enummodule
35
+ end
36
+ end
@@ -0,0 +1,57 @@
1
+ require "twirbet"
2
+ require_relative "clientcompat_pb"
3
+
4
+ module Twirp
5
+ module Clientcompat
6
+ module CompatService
7
+ module Handler
8
+ extend T::Sig
9
+ extend T::Helpers
10
+
11
+ interface!
12
+
13
+ sig { abstract.params(request: Req).returns(Resp) }
14
+ def real_method(request); end
15
+
16
+ sig { abstract.params(request: Empty).returns(Empty) }
17
+ def noop_method(request); end
18
+ end
19
+
20
+ class Service < Twirbet::Service
21
+ extend T::Sig
22
+
23
+ package "twirp.clientcompat"
24
+ service "CompatService"
25
+
26
+ rpc "Method", Req, Resp, ruby_method: :real_method
27
+ rpc "NoopMethod", Empty, Empty, ruby_method: :noop_method
28
+
29
+ sig { params(handler: Handler).void }
30
+ def initialize(handler)
31
+ super(handler)
32
+ end
33
+ end
34
+
35
+ class Client < Twirbet::Client
36
+ extend T::Sig
37
+ include Handler
38
+
39
+ package "twirp.clientcompat"
40
+ service "CompatService"
41
+
42
+ rpc "Method", Req, Resp, ruby_method: :real_method
43
+ rpc "NoopMethod", Empty, Empty, ruby_method: :noop_method
44
+
45
+ sig { override.params(request: Req).returns(Resp) }
46
+ def real_method(request)
47
+ call("Method", request)
48
+ end
49
+
50
+ sig { override.params(request: Empty).returns(Empty) }
51
+ def noop_method(request)
52
+ call("NoopMethod", request)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "twirbet", path: "../.."
6
+
7
+ gem "puma", "~> 6.0"
8
+
9
+ gem "sorbet", "~> 0.5.10595"
10
+
11
+ gem "tapioca", "~> 0.10.3"
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ twirbet (0.1.0)
5
+ google-protobuf (~> 3.21)
6
+ rack (~> 3.0)
7
+ sorbet-runtime (~> 0.5.10595)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.4.2)
13
+ diff-lcs (1.5.0)
14
+ google-protobuf (3.21.12)
15
+ netrc (0.11.0)
16
+ nio4r (2.5.8)
17
+ parallel (1.22.1)
18
+ parser (3.1.3.0)
19
+ ast (~> 2.4.1)
20
+ puma (6.0.0)
21
+ nio4r (~> 2.0)
22
+ rack (3.0.2)
23
+ rbi (0.0.16)
24
+ ast
25
+ parser (>= 2.6.4.0)
26
+ sorbet-runtime (>= 0.5.9204)
27
+ unparser
28
+ sorbet (0.5.10595)
29
+ sorbet-static (= 0.5.10595)
30
+ sorbet-runtime (0.5.10595)
31
+ sorbet-static (0.5.10595-universal-darwin-21)
32
+ sorbet-static-and-runtime (0.5.10595)
33
+ sorbet (= 0.5.10595)
34
+ sorbet-runtime (= 0.5.10595)
35
+ spoom (1.1.15)
36
+ sorbet (>= 0.5.10187)
37
+ sorbet-runtime (>= 0.5.9204)
38
+ thor (>= 0.19.2)
39
+ tapioca (0.10.3)
40
+ bundler (>= 1.17.3)
41
+ netrc (>= 0.11.0)
42
+ parallel (>= 1.21.0)
43
+ rbi (~> 0.0.0, >= 0.0.16)
44
+ sorbet-static-and-runtime (>= 0.5.9892)
45
+ spoom (~> 1.1.0, >= 1.1.11)
46
+ thor (>= 1.2.0)
47
+ yard-sorbet
48
+ thor (1.2.1)
49
+ unparser (0.6.5)
50
+ diff-lcs (~> 1.3)
51
+ parser (>= 3.1.0)
52
+ webrick (1.7.0)
53
+ yard (0.9.28)
54
+ webrick (~> 1.7.0)
55
+ yard-sorbet (0.7.0)
56
+ sorbet-runtime (>= 0.5)
57
+ yard (>= 0.9)
58
+
59
+ PLATFORMS
60
+ arm64-darwin-21
61
+
62
+ DEPENDENCIES
63
+ puma (~> 6.0)
64
+ sorbet (~> 0.5.10595)
65
+ tapioca (~> 0.10.3)
66
+ twirbet!
67
+
68
+ BUNDLED WITH
69
+ 2.3.26
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'puma' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("puma", "puma")
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'pumactl' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("puma", "pumactl")