taro 2.3.0 → 2.5.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 +12 -0
- data/README.md +28 -5
- data/lib/taro/export/open_api_v3.rb +2 -2
- data/lib/taro/types/base_type.rb +1 -0
- data/lib/taro/types/field.rb +4 -0
- data/lib/taro/types/object_types/page_type.rb +6 -4
- data/lib/taro/types/object_types/page_with_total_count_type.rb +26 -0
- data/lib/taro/types/shared/openapi_format.rb +61 -0
- data/lib/taro/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8f629d8573ed34c2d60303a387e99cae4cc9fcb0b14901d7080def1e27d0d90
|
4
|
+
data.tar.gz: 40c3ae606ade65922c5b69f9dd86353f2740d061b6d7094f61abe906e5f9198f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34b8e8d9ef5c2f016f56a887b674fa243ae6074fc59e4d29a1cb1873c4dfc3e87d8c24a37dd93a461ad71fc0fd38849462360bed7f6f9a1cca89e37fb3ad192b
|
7
|
+
data.tar.gz: d99f3bdc2e40e555a1a0b54dcac6a62d5774b6ae2c7c0d5e05c5ee0f1457864af696b37949173d8189769b03b5d9ce589eb1f49d855209c5c2bccadf32b51d84
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [2.5.0] - 2025-04-16
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Support for setting `openapi_format` for types and during export
|
8
|
+
|
9
|
+
## [2.4.0] - 2025-03-11
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- `PageWithTotalCountType` for paginated responses with a total count
|
14
|
+
|
3
15
|
## [2.3.0] - 2025-02-24
|
4
16
|
|
5
17
|
### Added
|
data/README.md
CHANGED
@@ -65,7 +65,7 @@ class BikesController < ApplicationController
|
|
65
65
|
|
66
66
|
# Support for arrays and paginated lists is built-in.
|
67
67
|
api 'List all bikes'
|
68
|
-
returns code: :ok, array_of: 'BikeType', desc: '
|
68
|
+
returns code: :ok, array_of: 'BikeType', desc: 'List of bikes'
|
69
69
|
def index
|
70
70
|
render json: BikeType.array.render(Bike.all)
|
71
71
|
end
|
@@ -89,9 +89,6 @@ class BikeType < ObjectType
|
|
89
89
|
# Fields can reference other types and arrays of values
|
90
90
|
field :users, array_of: 'UserType', null: false
|
91
91
|
|
92
|
-
# Pagination is built-in for big lists
|
93
|
-
field :parts, page_of: 'PartType', null: false
|
94
|
-
|
95
92
|
# Custom methods can be chosen to resolve fields
|
96
93
|
field :has_brand, type: 'Boolean', null: false, method: :brand?
|
97
94
|
|
@@ -273,6 +270,32 @@ class BikeType < ObjectType
|
|
273
270
|
end
|
274
271
|
```
|
275
272
|
|
273
|
+
### Pagination
|
274
|
+
|
275
|
+
Use `page_of:` to declare a paginated response. Call `page.render` on a type to render a page of records.
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
api 'List all bikes'
|
279
|
+
param :cursor, type: 'String', null: true, desc: 'Show bikes after this cursor'
|
280
|
+
returns code: :ok, page_of: 'BikeType', desc: 'A page of bikes'
|
281
|
+
def index
|
282
|
+
render json: BikeType.page.render(Bike.all, after: params[:cursor])
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
286
|
+
By default, the response does not include a total count. To include it, use `page_with_total_count`:
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
api 'List all bikes'
|
290
|
+
param :cursor, type: 'String', null: true, desc: 'Show bikes after this cursor'
|
291
|
+
returns code: :ok, page_with_total_count_of: 'BikeType', desc: 'A page of bikes'
|
292
|
+
def index
|
293
|
+
render json: BikeType.page_with_total_count.render(Bike.all, after: params[:cursor])
|
294
|
+
end
|
295
|
+
```
|
296
|
+
|
297
|
+
See also: [Derived types](#derived-types).
|
298
|
+
|
276
299
|
## FAQ
|
277
300
|
|
278
301
|
### How do I render API docs?
|
@@ -343,6 +366,7 @@ Why e.g. `field :id, type: 'UUID'` instead of `field :id, type: UUID`?
|
|
343
366
|
|
344
367
|
The purpose of this is to reduce unnecessary autoloading of the whole type dependency tree in dev and test environments.
|
345
368
|
|
369
|
+
<a name="derived-types"></a>
|
346
370
|
### Can I define my own derived types like `page_of` or `array_of`?
|
347
371
|
|
348
372
|
Yes.
|
@@ -386,7 +410,6 @@ end
|
|
386
410
|
- mixed arrays
|
387
411
|
- mixed enums
|
388
412
|
- nullable enums
|
389
|
-
- string format specifications (e.g. binary, int64, password ...)
|
390
413
|
- string minLength and maxLength (substitute: `self.pattern = /\A.{3,5}\z/`)
|
391
414
|
- number minimum, exclusiveMinimum, maximum, multipleOf
|
392
415
|
- readOnly, writeOnly
|
@@ -129,7 +129,7 @@ class Taro::Export::OpenAPIv3 < Taro::Export::Base # rubocop:disable Metrics/Cla
|
|
129
129
|
|
130
130
|
def export_type(type)
|
131
131
|
if type < Taro::Types::ScalarType && !custom_scalar_type?(type)
|
132
|
-
{ type: type.openapi_type }
|
132
|
+
{ type: type.openapi_type, format: type.openapi_format }.compact
|
133
133
|
else
|
134
134
|
extract_component_ref(type)
|
135
135
|
end
|
@@ -148,7 +148,7 @@ class Taro::Export::OpenAPIv3 < Taro::Export::Base # rubocop:disable Metrics/Cla
|
|
148
148
|
end
|
149
149
|
|
150
150
|
def export_scalar_field(field)
|
151
|
-
base = { type: field.openapi_type }
|
151
|
+
base = { type: field.openapi_type, format: field.openapi_format }.compact
|
152
152
|
# Using oneOf seems more correct than an array of types
|
153
153
|
# as it puts props like format together with the main type.
|
154
154
|
# https://github.com/OAI/OpenAPI-Specification/issues/3148
|
data/lib/taro/types/base_type.rb
CHANGED
@@ -17,6 +17,7 @@ Taro::Types::BaseType = Struct.new(:object) do
|
|
17
17
|
extend Taro::Types::Shared::Description
|
18
18
|
extend Taro::Types::Shared::Equivalence
|
19
19
|
extend Taro::Types::Shared::Name
|
20
|
+
extend Taro::Types::Shared::OpenAPIFormat
|
20
21
|
extend Taro::Types::Shared::OpenAPIName
|
21
22
|
extend Taro::Types::Shared::OpenAPIType
|
22
23
|
extend Taro::Types::Shared::Rendering
|
data/lib/taro/types/field.rb
CHANGED
@@ -13,14 +13,16 @@ class Taro::Types::ObjectTypes::PageType < Taro::Types::ResponseType
|
|
13
13
|
field(:page_info, type: 'Taro::Types::ObjectTypes::PageInfoType', null: false)
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.render(relation,
|
16
|
+
def self.render(relation, **)
|
17
|
+
super(paginate(relation, **))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.paginate(relation, after:, limit: 20, order_by: nil, order: nil)
|
17
21
|
result = RailsCursorPagination::Paginator.new(
|
18
22
|
relation, limit:, order_by:, order:, after:
|
19
23
|
).fetch
|
20
|
-
|
21
24
|
result[:page].map! { |el| el.fetch(:data) }
|
22
|
-
|
23
|
-
super(result)
|
25
|
+
result
|
24
26
|
end
|
25
27
|
|
26
28
|
def self.default_openapi_name
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This is an expanded `PageType` that adds a `total_count` field
|
2
|
+
# to show the total number of records in the paginated relation.
|
3
|
+
# It is not recommended for very large relations where counting might be slow.
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
# - `returns code: :ok, page_with_total_count_of: 'UserType'`
|
7
|
+
# - `UserType.page_with_total_count.render(User.all, after: params[:cursor])`
|
8
|
+
#
|
9
|
+
# The gem rails_cursor_pagination must be installed to use this.
|
10
|
+
#
|
11
|
+
class Taro::Types::ObjectTypes::PageWithTotalCountType < Taro::Types::ObjectTypes::PageType
|
12
|
+
def self.derive_from(from_type)
|
13
|
+
super
|
14
|
+
field(:total_count, type: 'Integer', null: false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.paginate(relation, **)
|
18
|
+
super.merge(total_count: relation.count)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.default_openapi_name
|
22
|
+
"#{item_type.openapi_name}_PageWithTotalCount"
|
23
|
+
end
|
24
|
+
|
25
|
+
define_derived_type :page_with_total_count, 'Taro::Types::ObjectTypes::PageWithTotalCountType'
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Provides a setter and getter for type classes' `openapi_format`,
|
2
|
+
# for use in the OpenAPI export.
|
3
|
+
module Taro::Types::Shared::OpenAPIFormat
|
4
|
+
OPENAPI_STRING_FORMATS = %i[
|
5
|
+
date
|
6
|
+
date-time
|
7
|
+
password
|
8
|
+
byte
|
9
|
+
binary
|
10
|
+
email
|
11
|
+
uuid
|
12
|
+
uri
|
13
|
+
hostname
|
14
|
+
ipv4
|
15
|
+
ipv6
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
OPENAPI_INTEGER_FORMATS = %i[
|
19
|
+
int32
|
20
|
+
int64
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
OPENAPI_NUMBER_FORMATS = %i[
|
24
|
+
float
|
25
|
+
double
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
def openapi_format
|
29
|
+
return unless @openapi_format
|
30
|
+
|
31
|
+
unless valid_formats_for_openapi_type.include?(@openapi_format)
|
32
|
+
raise(Taro::ArgumentError, "openapi_format #{@openapi_format.inspect} is invalid for openapi_type #{@openapi_type.inspect}, must be one for #{valid_formats_for_openapi_type}")
|
33
|
+
end
|
34
|
+
|
35
|
+
@openapi_format
|
36
|
+
end
|
37
|
+
|
38
|
+
def openapi_format=(arg)
|
39
|
+
@openapi_format = arg
|
40
|
+
end
|
41
|
+
|
42
|
+
def inherited(subclass)
|
43
|
+
subclass.instance_variable_set(:@openapi_format, @openapi_format)
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def valid_formats_for_openapi_type
|
50
|
+
case @openapi_type
|
51
|
+
when :string
|
52
|
+
OPENAPI_STRING_FORMATS
|
53
|
+
when :integer
|
54
|
+
OPENAPI_INTEGER_FORMATS
|
55
|
+
when :number
|
56
|
+
OPENAPI_NUMBER_FORMATS
|
57
|
+
else
|
58
|
+
[]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/taro/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: taro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janosch Müller
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-
|
12
|
+
date: 2025-04-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/taro/types/object_types/no_content_type.rb
|
90
90
|
- lib/taro/types/object_types/page_info_type.rb
|
91
91
|
- lib/taro/types/object_types/page_type.rb
|
92
|
+
- lib/taro/types/object_types/page_with_total_count_type.rb
|
92
93
|
- lib/taro/types/rails_params_type.rb
|
93
94
|
- lib/taro/types/response_type.rb
|
94
95
|
- lib/taro/types/scalar/boolean_type.rb
|
@@ -114,6 +115,7 @@ files:
|
|
114
115
|
- lib/taro/types/shared/item_type.rb
|
115
116
|
- lib/taro/types/shared/name.rb
|
116
117
|
- lib/taro/types/shared/object_coercion.rb
|
118
|
+
- lib/taro/types/shared/openapi_format.rb
|
117
119
|
- lib/taro/types/shared/openapi_name.rb
|
118
120
|
- lib/taro/types/shared/openapi_type.rb
|
119
121
|
- lib/taro/types/shared/pattern.rb
|
@@ -145,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
147
|
- !ruby/object:Gem::Version
|
146
148
|
version: '0'
|
147
149
|
requirements: []
|
148
|
-
rubygems_version: 3.5.
|
150
|
+
rubygems_version: 3.5.16
|
149
151
|
signing_key:
|
150
152
|
specification_version: 4
|
151
153
|
summary: Typed Api using Ruby Objects.
|