grape_sorbet 0.0.2 → 0.0.4

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: 3aadd0dde4fcc5037da59fbc26226c5d54d94686cc4024875e9cf9e21e547df8
4
- data.tar.gz: 9ca6394902e1aea0a6facfcb584c3bac8c03ff580f5a3c8501962fcb737d7154
3
+ metadata.gz: aa4f8d64cc6cbf5839f525d1c1e246386510695be350c4bf1ed1298b52b8c9a4
4
+ data.tar.gz: baeca4c981155f04394d3dab717a300c923f41aa063516c4eb0430943e0ba756
5
5
  SHA512:
6
- metadata.gz: 212aad3e25427f5d9329061e20d308d54daea04584c65d6cd0c5f8d542b7396287cb43a76f93999fea67c24883610e6f9d56e399bf59f7a65737ad51b21b4b41
7
- data.tar.gz: 56f4c190b13f6763ad0e2a4b051346011eb976c3664de34e5b915f886a2c2970054b8e1946b5738fa2f439c1ecb88fc1f094d80e63145529a0e9b861fb0faa69
6
+ metadata.gz: 9a7f6cb172c0c73adf41a2992b620f45962459baeeb7f19cc916036776a010018a28a5f0dac752a55a2e1c623ee4e394a6654fd3f2139750e73fdc278a5f8a6d
7
+ data.tar.gz: 59580b70030d1d8d013191c55671a82daa854e1a536ecc67acb1a1ee70e1e907086a76b9eddb5022eadb03161c0043c241c7fc5f8a831c4cdf0b1c0f12e09597
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.0.4 (2024-06-24)
2
+
3
+ - Update `grape.rbi`
4
+
5
+ ## 0.0.3 (2024-06-05)
6
+
7
+ - Better support for callbacks
8
+
1
9
  ## 0.0.2 (2024-06-05)
2
10
 
3
11
  - Added support for callbacks (`before`, `after`, etc.)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grape_sorbet (0.0.2)
4
+ grape_sorbet (0.0.4)
5
5
  activesupport
6
6
  grape (~> 2.0)
7
7
  sorbet-runtime (~> 0.5.10741)
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # grape_sorbet
2
2
 
3
3
  [![Build Status](https://github.com/thatch-health/grape_sorbet/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/thatch-health/grape_sorbet/actions?query=branch%3Amain)
4
+ [![Gem Version ](https://img.shields.io/gem/v/grape_sorbet.svg?style=flat)](https://rubygems.org/gems/grape_sorbet)
4
5
 
5
6
  grape_sorbet is a gem that provides hand written signatures and a Tapioca DSL compiler that makes it more pleasant to use the [Grape](https://github.com/ruby-grape/grape) API framework in Ruby projects that use the [Sorbet](https://sorbet.org/) typechecker.
6
7
 
@@ -90,7 +91,29 @@ module Twitter
90
91
  end
91
92
  ```
92
93
 
93
- At this point Sorbet is still reporting errors in the `get :home_timeline` block, because it doesn't know that these blocks are executed in a context where the `Helpers` module methods will be available. The Tapioca compiler provided by this gem will fix that. Run `bundle exec tapioca dsl`. This should generate a `sorbet/rbi/dsl/twitter/api.rbi` file (assuming the source file is in `lib/twitter/api.rb`). After this,
94
+ At this point Sorbet is still reporting errors in the `get :home_timeline` block, because it doesn't know that these blocks are executed in a context where the `Helpers` module methods will be available. The Tapioca compiler provided by this gem will fix that. Run `bundle exec tapioca dsl`. This should generate a `sorbet/rbi/dsl/twitter/api.rbi` file (assuming the source file is in `lib/twitter/api.rb`).
95
+
96
+ After this, Sorbet should no longer report any errors.
97
+
98
+ ## Limitations and known issues
99
+
100
+ ### Subclassing from `Grape::API::Instance` instead of `Grape::API`
101
+
102
+ Grape overrides `Grape::API.new` and uses the `inherited` hook so that subclasses of `Grape::API` are really subclasses of `Grape::API::Instance`.
103
+
104
+ This might be fixable in a future update of grape_sorbet, but is very low priority.
105
+
106
+ ### Not being able to call `helpers` with block arguments
107
+
108
+ Possibly fixable in a future update.
109
+
110
+ ### Having to use `T.bind(self, T.any(Grape::Endpoint, <HelpersModuleName>))` in helper methods
111
+
112
+ Possibly fixable in a future update.
113
+
114
+ ### Having to use `T.bind(self, T.any(Grape::Endpoint, <HelpersModuleName>))` in `before` and `after` callback blocks
115
+
116
+ The compiler already generates proper signatures for callback methods so `T.bind` should not be needed (and is in fact unneeded for the other callback methods, `before_validation`, `after_validation` and `finally`). The reason it doesn't work for `before` and `after` is because of a [bug](https://github.com/sorbet/sorbet/issues/7950) in Sorbet itself.
94
117
 
95
118
  ## Development
96
119
 
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module GrapeSorbet
5
- VERSION = "0.0.2"
5
+ VERSION = "0.0.4"
6
6
  end
@@ -80,13 +80,13 @@ module Tapioca
80
80
  end
81
81
  end
82
82
 
83
- HTTP_VERB_METHODS = T.let(
84
- [:get, :post, :put, :patch, :delete, :head, :options].freeze,
83
+ CALLBACKS_METHODS = T.let(
84
+ [:before, :before_validation, :after_validation, :after, :finally].freeze,
85
85
  T::Array[Symbol],
86
86
  )
87
87
 
88
- CALLBACKS_METHODS = T.let(
89
- [:before, :before_validation, :after_validation, :after, :finally].freeze,
88
+ HTTP_VERB_METHODS = T.let(
89
+ [:get, :post, :put, :patch, :delete, :head, :options].freeze,
90
90
  T::Array[Symbol],
91
91
  )
92
92
 
@@ -100,6 +100,14 @@ module Tapioca
100
100
  )
101
101
  end
102
102
 
103
+ sig { returns(RBI::Scope) }
104
+ def callbacks_methods_module
105
+ @callbacks_methods_module ||= T.let(
106
+ api.create_module(CallbacksMethodsModuleName),
107
+ T.nilable(RBI::Scope),
108
+ )
109
+ end
110
+
103
111
  sig { returns(RBI::Scope) }
104
112
  def routing_methods_module
105
113
  @routing_methods_module ||= T.let(
@@ -110,6 +118,7 @@ module Tapioca
110
118
 
111
119
  sig { void }
112
120
  def create_classes_and_includes
121
+ api.create_extend(CallbacksMethodsModuleName)
113
122
  api.create_extend(RoutingMethodsModuleName)
114
123
  create_api_class
115
124
  create_endpoint_class
@@ -141,6 +150,19 @@ module Tapioca
141
150
  end
142
151
  end
143
152
 
153
+ sig { void }
154
+ def create_callbacks_methods
155
+ CALLBACKS_METHODS.each do |callback|
156
+ callbacks_methods_module.create_method(
157
+ callback.to_s,
158
+ parameters: [
159
+ create_block_param("block", type: "T.proc.bind(#{EndpointClassName}).void"),
160
+ ],
161
+ return_type: "void",
162
+ )
163
+ end
164
+ end
165
+
144
166
  sig { void }
145
167
  def create_routing_methods
146
168
  HTTP_VERB_METHODS.each do |verb|
@@ -148,7 +170,7 @@ module Tapioca
148
170
  verb.to_s,
149
171
  parameters: [
150
172
  create_rest_param("args", type: "T.untyped"),
151
- create_block_param("blk", type: "T.nilable(T.proc.bind(#{EndpointClassName}).void)"),
173
+ create_block_param("block", type: "T.nilable(T.proc.bind(#{EndpointClassName}).void)"),
152
174
  ],
153
175
  return_type: "void",
154
176
  )
@@ -158,26 +180,12 @@ module Tapioca
158
180
  "route_param",
159
181
  parameters: [
160
182
  create_param("param", type: "Symbol"),
161
- create_opt_param("options", type: "T.nilable(T::Hash[Symbol, T.untyped])", default: "nil"),
162
- create_block_param("blk", type: "T.nilable(T.proc.bind(T.class_of(#{APIInstanceClassName})).void)"),
183
+ create_opt_param("options", type: "T::Hash[Symbol, T.untyped]", default: "{}"),
184
+ create_block_param("block", type: "T.nilable(T.proc.bind(T.class_of(#{APIInstanceClassName})).void)"),
163
185
  ],
164
186
  return_type: "void",
165
187
  )
166
188
  end
167
-
168
- sig { void }
169
- def create_callbacks_methods
170
- CALLBACKS_METHODS.each do |callback|
171
- routing_methods_module.create_method(
172
- callback.to_s,
173
- parameters: [
174
- create_rest_param("args", type: "T.untyped"),
175
- create_block_param("blk", type: "T.nilable(T.proc.bind(#{EndpointClassName}).void)"),
176
- ],
177
- return_type: "void",
178
- )
179
- end
180
- end
181
189
  end
182
190
  end
183
191
  end
@@ -7,6 +7,7 @@ module Tapioca
7
7
  module GrapeConstantsHelper
8
8
  extend T::Sig
9
9
 
10
+ CallbacksMethodsModuleName = "GeneratedCallbacksMethods"
10
11
  RoutingMethodsModuleName = "GeneratedRoutingMethods"
11
12
 
12
13
  APIInstanceClassName = "PrivateAPIInstance"
data/rbi/grape.rbi CHANGED
@@ -2,107 +2,122 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Grape
5
- module DSL::Callbacks::ClassMethods
6
- sig { params(block: T.proc.bind(Grape::Endpoint).void).void }
7
- def before(&block); end
8
- end
9
-
10
- module DSL::Desc
11
- # grape evaluates config_block in the context of a dynamically created module that implements the DSL it exposes
12
- # at runtime. There's no good way to represent this statically, so block is just typed as T.untyped to prevent
13
- # Sorbet from complaining that the DSL methods don't exist.
14
- sig do
15
- params(
16
- description: String,
17
- options: T.nilable(T::Hash[Symbol, T.untyped]),
18
- config_block: T.nilable(T.proc.bind(T.untyped).void),
19
- ).void
5
+ module DSL
6
+ module Desc
7
+ # grape evaluates config_block in the context of a dynamically created module that implements the DSL it exposes
8
+ # at runtime. There's no good way to represent this statically, so block is just typed as T.untyped to prevent
9
+ # Sorbet from complaining that the DSL methods don't exist.
10
+ sig do
11
+ params(
12
+ description: String,
13
+ options: T.nilable(T::Hash[Symbol, T.untyped]),
14
+ config_block: T.nilable(T.proc.bind(T.untyped).void),
15
+ ).void
16
+ end
17
+ def desc(description, options = T.unsafe(nil), &config_block); end
20
18
  end
21
- def desc(description, options = T.unsafe(nil), &config_block); end
22
- end
23
19
 
24
- module DSL::RequestResponse::ClassMethods
25
- sig { params(args: T.untyped, block: T.proc.bind(Grape::Endpoint).void).void }
26
- def rescue_from(*args, &block); end
27
- end
28
-
29
- module DSL::Routing::ClassMethods
30
- # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
31
- sig do
32
- params(
33
- args: T.untyped,
34
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
35
- ).void
20
+ module Helpers
21
+ module BaseHelper
22
+ sig { params(name: Symbol, block: T.proc.bind(Grape::Validations::ParamsScope).void).void }
23
+ def params(name, &block); end
24
+ end
36
25
  end
37
- def delete(*args, &block); end
38
26
 
39
- # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
40
- sig do
41
- params(
42
- args: T.untyped,
43
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
44
- ).void
27
+ module RequestResponse
28
+ module ClassMethods
29
+ sig { params(args: T.untyped, block: T.proc.bind(Grape::Endpoint).void).void }
30
+ def rescue_from(*args, &block); end
31
+ end
45
32
  end
46
- def get(*args, &block); end
47
33
 
48
- # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
49
- sig do
50
- params(
51
- args: T.untyped,
52
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
53
- ).void
54
- end
55
- def options(*args, &block); end
34
+ module Routing
35
+ module ClassMethods
36
+ # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
37
+ sig do
38
+ params(
39
+ args: T.untyped,
40
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
41
+ ).void
42
+ end
43
+ def delete(*args, &block); end
56
44
 
57
- # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
58
- sig do
59
- params(
60
- args: T.untyped,
61
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
62
- ).void
63
- end
64
- def patch(*args, &block); end
45
+ # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
46
+ sig do
47
+ params(
48
+ args: T.untyped,
49
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
50
+ ).void
51
+ end
52
+ def get(*args, &block); end
65
53
 
66
- # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
67
- sig do
68
- params(
69
- args: T.untyped,
70
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
71
- ).void
72
- end
73
- def post(*args, &block); end
54
+ # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
55
+ sig do
56
+ params(
57
+ args: T.untyped,
58
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
59
+ ).void
60
+ end
61
+ def options(*args, &block); end
74
62
 
75
- # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
76
- sig do
77
- params(
78
- args: T.untyped,
79
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
80
- ).void
81
- end
82
- def put(*args, &block); end
63
+ # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
64
+ sig do
65
+ params(
66
+ args: T.untyped,
67
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
68
+ ).void
69
+ end
70
+ def patch(*args, &block); end
71
+
72
+ # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
73
+ sig do
74
+ params(
75
+ args: T.untyped,
76
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
77
+ ).void
78
+ end
79
+ def post(*args, &block); end
80
+
81
+ # @shim: https://github.com/ruby-grape/grape/blob/v2.0.0/lib/grape/dsl/routing.rb#L148-L154
82
+ sig do
83
+ params(
84
+ args: T.untyped,
85
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
86
+ ).void
87
+ end
88
+ def put(*args, &block); end
89
+
90
+ sig do
91
+ params(
92
+ methods: T.any(Symbol, String, T::Array[String]),
93
+ paths: T.nilable(T.any(String, T::Array[String])),
94
+ route_options: T.nilable(T::Hash[Symbol, T.untyped]),
95
+ block: T.nilable(T.proc.bind(Grape::Endpoint).void),
96
+ ).void
97
+ end
98
+ def route(methods, paths = T.unsafe(nil), route_options = T.unsafe(nil), &block); end
83
99
 
84
- sig do
85
- params(
86
- methods: T.any(Symbol, String, T::Array[String]),
87
- paths: T.nilable(T.any(String, T::Array[String])),
88
- route_options: T.nilable(T::Hash[Symbol, T.untyped]),
89
- block: T.nilable(T.proc.bind(Grape::Endpoint).void),
90
- ).void
100
+ sig do
101
+ params(
102
+ param: Symbol,
103
+ options: T.nilable(T::Hash[Symbol, T.untyped]),
104
+ block: T.nilable(T.proc.bind(T.class_of(Grape::API::Instance)).void),
105
+ ).void
106
+ end
107
+ def route_param(param, options = T.unsafe(nil), &block); end
108
+ end
91
109
  end
92
- def route(methods, paths = T.unsafe(nil), route_options = T.unsafe(nil), &block); end
93
110
 
94
- sig do
95
- params(
96
- param: Symbol,
97
- options: T.nilable(T::Hash[Symbol, T.untyped]),
98
- block: T.nilable(T.proc.bind(T.class_of(Grape::API::Instance)).void),
99
- ).void
111
+ module Validations
112
+ module ClassMethods
113
+ sig { params(block: T.proc.bind(Grape::Validations::ParamsScope).void).void }
114
+ def params(&block); end
115
+ end
100
116
  end
101
- def route_param(param, options = T.unsafe(nil), &block); end
102
117
  end
103
118
 
104
- module DSL::Validations::ClassMethods
105
- sig { params(block: T.proc.bind(Grape::Validations::ParamsScope).void).void }
106
- def params(&block); end
119
+ class Endpoint
120
+ sig { returns(Grape::Request) }
121
+ def request; end
107
122
  end
108
123
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape_sorbet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thatch Health, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-05 00:00:00.000000000 Z
11
+ date: 2024-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
100
  requirements: []
101
- rubygems_version: 3.5.9
101
+ rubygems_version: 3.5.13
102
102
  signing_key:
103
103
  specification_version: 4
104
104
  summary: Sorbet signatures and Tapioca DSL compiler for Grape.