grape_sorbet 0.0.2 → 0.0.4
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 +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +24 -1
- data/lib/grape_sorbet/version.rb +1 -1
- data/lib/tapioca/dsl/compilers/grape_endpoints.rb +29 -21
- data/lib/tapioca/dsl/helpers/grape_constants_helper.rb +1 -0
- data/rbi/grape.rbi +102 -87
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa4f8d64cc6cbf5839f525d1c1e246386510695be350c4bf1ed1298b52b8c9a4
|
4
|
+
data.tar.gz: baeca4c981155f04394d3dab717a300c923f41aa063516c4eb0430943e0ba756
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a7f6cb172c0c73adf41a2992b620f45962459baeeb7f19cc916036776a010018a28a5f0dac752a55a2e1c623ee4e394a6654fd3f2139750e73fdc278a5f8a6d
|
7
|
+
data.tar.gz: 59580b70030d1d8d013191c55671a82daa854e1a536ecc67acb1a1ee70e1e907086a76b9eddb5022eadb03161c0043c241c7fc5f8a831c4cdf0b1c0f12e09597
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# grape_sorbet
|
2
2
|
|
3
3
|
[](https://github.com/thatch-health/grape_sorbet/actions?query=branch%3Amain)
|
4
|
+
[](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`).
|
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
|
|
data/lib/grape_sorbet/version.rb
CHANGED
@@ -80,13 +80,13 @@ module Tapioca
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
|
84
|
-
[:
|
83
|
+
CALLBACKS_METHODS = T.let(
|
84
|
+
[:before, :before_validation, :after_validation, :after, :finally].freeze,
|
85
85
|
T::Array[Symbol],
|
86
86
|
)
|
87
87
|
|
88
|
-
|
89
|
-
[:
|
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("
|
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
|
162
|
-
create_block_param("
|
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
|
data/rbi/grape.rbi
CHANGED
@@ -2,107 +2,122 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module Grape
|
5
|
-
module DSL
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
args
|
43
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
105
|
-
sig {
|
106
|
-
def
|
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.
|
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-
|
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.
|
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.
|