jpie 0.4.0 → 0.4.1
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/{.aiconfig → .cursorrules} +14 -2
- data/CHANGELOG.md +19 -0
- data/README.md +139 -965
- data/examples/basic_example.md +146 -0
- data/examples/including_related_resources.md +491 -0
- data/examples/resource_attribute_configuration.md +147 -0
- data/examples/resource_meta_configuration.md +244 -0
- data/examples/single_table_inheritance.md +160 -0
- data/lib/jpie/controller/crud_actions.rb +10 -0
- data/lib/jpie/controller/error_handling.rb +168 -17
- data/lib/jpie/controller/json_api_validation.rb +171 -0
- data/lib/jpie/controller.rb +2 -0
- data/lib/jpie/errors.rb +41 -0
- data/lib/jpie/resource/attributable.rb +21 -2
- data/lib/jpie/resource.rb +26 -0
- data/lib/jpie/version.rb +1 -1
- metadata +9 -3
@@ -0,0 +1,146 @@
|
|
1
|
+
# Basic JPie Example
|
2
|
+
|
3
|
+
This example shows the minimal setup to get a JPie resource working with HTTP requests and responses.
|
4
|
+
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
### 1. Model (`app/models/user.rb`)
|
8
|
+
```ruby
|
9
|
+
class User < ActiveRecord::Base
|
10
|
+
validates :name, presence: true
|
11
|
+
validates :email, presence: true, uniqueness: true
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
### 2. Resource (`app/resources/user_resource.rb`)
|
16
|
+
```ruby
|
17
|
+
class UserResource < JPie::Resource
|
18
|
+
attributes :name, :email
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
### 3. Controller (`app/controllers/users_controller.rb`)
|
23
|
+
```ruby
|
24
|
+
class UsersController < ApplicationController
|
25
|
+
include JPie::Controller
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
### 4. Routes (`config/routes.rb`)
|
30
|
+
```ruby
|
31
|
+
Rails.application.routes.draw do
|
32
|
+
resources :users
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
## HTTP Examples
|
37
|
+
|
38
|
+
### Create User
|
39
|
+
```http
|
40
|
+
POST /users
|
41
|
+
Content-Type: application/vnd.api+json
|
42
|
+
|
43
|
+
{
|
44
|
+
"data": {
|
45
|
+
"type": "users",
|
46
|
+
"attributes": {
|
47
|
+
"name": "John Doe",
|
48
|
+
"email": "john@example.com"
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
HTTP/1.1 201 Created
|
54
|
+
Content-Type: application/vnd.api+json
|
55
|
+
|
56
|
+
{
|
57
|
+
"data": {
|
58
|
+
"id": "1",
|
59
|
+
"type": "users",
|
60
|
+
"attributes": {
|
61
|
+
"name": "John Doe",
|
62
|
+
"email": "john@example.com"
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
```
|
67
|
+
|
68
|
+
### Get All Users
|
69
|
+
```http
|
70
|
+
GET /users
|
71
|
+
Accept: application/vnd.api+json
|
72
|
+
|
73
|
+
HTTP/1.1 200 OK
|
74
|
+
Content-Type: application/vnd.api+json
|
75
|
+
|
76
|
+
{
|
77
|
+
"data": [
|
78
|
+
{
|
79
|
+
"id": "1",
|
80
|
+
"type": "users",
|
81
|
+
"attributes": {
|
82
|
+
"name": "John Doe",
|
83
|
+
"email": "john@example.com"
|
84
|
+
}
|
85
|
+
}
|
86
|
+
]
|
87
|
+
}
|
88
|
+
```
|
89
|
+
|
90
|
+
### Get Single User
|
91
|
+
```http
|
92
|
+
GET /users/1
|
93
|
+
Accept: application/vnd.api+json
|
94
|
+
|
95
|
+
HTTP/1.1 200 OK
|
96
|
+
Content-Type: application/vnd.api+json
|
97
|
+
|
98
|
+
{
|
99
|
+
"data": {
|
100
|
+
"id": "1",
|
101
|
+
"type": "users",
|
102
|
+
"attributes": {
|
103
|
+
"name": "John Doe",
|
104
|
+
"email": "john@example.com"
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
```
|
109
|
+
|
110
|
+
### Update User
|
111
|
+
```http
|
112
|
+
PATCH /users/1
|
113
|
+
Content-Type: application/vnd.api+json
|
114
|
+
|
115
|
+
{
|
116
|
+
"data": {
|
117
|
+
"id": "1",
|
118
|
+
"type": "users",
|
119
|
+
"attributes": {
|
120
|
+
"name": "Jane Doe"
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
HTTP/1.1 200 OK
|
126
|
+
Content-Type: application/vnd.api+json
|
127
|
+
|
128
|
+
{
|
129
|
+
"data": {
|
130
|
+
"id": "1",
|
131
|
+
"type": "users",
|
132
|
+
"attributes": {
|
133
|
+
"name": "Jane Doe",
|
134
|
+
"email": "john@example.com"
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
```
|
139
|
+
|
140
|
+
### Delete User
|
141
|
+
```http
|
142
|
+
DELETE /users/1
|
143
|
+
Accept: application/vnd.api+json
|
144
|
+
|
145
|
+
HTTP/1.1 204 No Content
|
146
|
+
```
|
@@ -0,0 +1,491 @@
|
|
1
|
+
# Including Related Resources Example
|
2
|
+
|
3
|
+
This example demonstrates how to include related resources in JPie responses using the `include` parameter, showcasing various relationship types and nested includes.
|
4
|
+
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
### 1. Models (`app/models/`)
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# app/models/user.rb
|
11
|
+
class User < ActiveRecord::Base
|
12
|
+
validates :name, presence: true
|
13
|
+
validates :email, presence: true, uniqueness: true
|
14
|
+
|
15
|
+
has_many :posts, dependent: :destroy
|
16
|
+
has_many :comments, dependent: :destroy
|
17
|
+
has_one :profile, dependent: :destroy
|
18
|
+
end
|
19
|
+
|
20
|
+
# app/models/post.rb
|
21
|
+
class Post < ActiveRecord::Base
|
22
|
+
validates :title, presence: true
|
23
|
+
validates :content, presence: true
|
24
|
+
|
25
|
+
belongs_to :user
|
26
|
+
has_many :comments, dependent: :destroy
|
27
|
+
has_many :tags, through: :taggings
|
28
|
+
end
|
29
|
+
|
30
|
+
# app/models/comment.rb
|
31
|
+
class Comment < ActiveRecord::Base
|
32
|
+
validates :content, presence: true
|
33
|
+
|
34
|
+
belongs_to :user
|
35
|
+
belongs_to :post
|
36
|
+
has_many :tags, through: :taggings
|
37
|
+
end
|
38
|
+
|
39
|
+
# app/models/profile.rb
|
40
|
+
class Profile < ActiveRecord::Base
|
41
|
+
validates :bio, presence: true
|
42
|
+
|
43
|
+
belongs_to :user
|
44
|
+
end
|
45
|
+
|
46
|
+
# app/models/tag.rb
|
47
|
+
class Tag < ActiveRecord::Base
|
48
|
+
validates :name, presence: true, uniqueness: true
|
49
|
+
|
50
|
+
has_many :taggings, dependent: :destroy
|
51
|
+
has_many :posts, through: :taggings, source: :taggable, source_type: 'Post'
|
52
|
+
has_many :comments, through: :taggings, source: :taggable, source_type: 'Comment'
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
### 2. Resources (`app/resources/`)
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
# app/resources/user_resource.rb
|
60
|
+
class UserResource < JPie::Resource
|
61
|
+
attributes :name, :email
|
62
|
+
meta_attributes :created_at, :updated_at
|
63
|
+
|
64
|
+
has_many :posts
|
65
|
+
has_many :comments
|
66
|
+
has_one :profile
|
67
|
+
end
|
68
|
+
|
69
|
+
# app/resources/post_resource.rb
|
70
|
+
class PostResource < JPie::Resource
|
71
|
+
attributes :title, :content
|
72
|
+
meta_attributes :created_at, :updated_at
|
73
|
+
|
74
|
+
has_one :user
|
75
|
+
has_many :comments
|
76
|
+
has_many :tags
|
77
|
+
end
|
78
|
+
|
79
|
+
# app/resources/comment_resource.rb
|
80
|
+
class CommentResource < JPie::Resource
|
81
|
+
attributes :content
|
82
|
+
meta_attributes :created_at, :updated_at
|
83
|
+
|
84
|
+
has_one :user
|
85
|
+
has_one :post
|
86
|
+
has_many :tags
|
87
|
+
end
|
88
|
+
|
89
|
+
# app/resources/profile_resource.rb
|
90
|
+
class ProfileResource < JPie::Resource
|
91
|
+
attributes :bio, :website
|
92
|
+
meta_attributes :created_at, :updated_at
|
93
|
+
|
94
|
+
has_one :user
|
95
|
+
end
|
96
|
+
|
97
|
+
# app/resources/tag_resource.rb
|
98
|
+
class TagResource < JPie::Resource
|
99
|
+
attributes :name
|
100
|
+
meta_attributes :created_at, :updated_at
|
101
|
+
|
102
|
+
has_many :posts
|
103
|
+
has_many :comments
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
### 3. Controller (`app/controllers/posts_controller.rb`)
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
class PostsController < ApplicationController
|
111
|
+
include JPie::Controller
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
## HTTP Examples
|
116
|
+
|
117
|
+
### Create Post with Included User
|
118
|
+
```http
|
119
|
+
POST /posts?include=user
|
120
|
+
Content-Type: application/vnd.api+json
|
121
|
+
|
122
|
+
{
|
123
|
+
"data": {
|
124
|
+
"type": "posts",
|
125
|
+
"attributes": {
|
126
|
+
"title": "Getting Started with JPie",
|
127
|
+
"content": "This post explains how to use JPie...",
|
128
|
+
"user_id": 1
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
HTTP/1.1 201 Created
|
134
|
+
Content-Type: application/vnd.api+json
|
135
|
+
|
136
|
+
{
|
137
|
+
"data": {
|
138
|
+
"id": "1",
|
139
|
+
"type": "posts",
|
140
|
+
"attributes": {
|
141
|
+
"title": "Getting Started with JPie",
|
142
|
+
"content": "This post explains how to use JPie..."
|
143
|
+
},
|
144
|
+
"meta": {
|
145
|
+
"created_at": "2024-01-15T10:30:00Z",
|
146
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
147
|
+
}
|
148
|
+
},
|
149
|
+
"included": [
|
150
|
+
{
|
151
|
+
"id": "1",
|
152
|
+
"type": "users",
|
153
|
+
"attributes": {
|
154
|
+
"name": "John Doe",
|
155
|
+
"email": "john@example.com"
|
156
|
+
},
|
157
|
+
"meta": {
|
158
|
+
"created_at": "2024-01-10T09:00:00Z",
|
159
|
+
"updated_at": "2024-01-10T09:00:00Z"
|
160
|
+
}
|
161
|
+
}
|
162
|
+
]
|
163
|
+
}
|
164
|
+
```
|
165
|
+
|
166
|
+
### Update Post with Included User and Comments
|
167
|
+
```http
|
168
|
+
PATCH /posts/1?include=user,comments
|
169
|
+
Content-Type: application/vnd.api+json
|
170
|
+
|
171
|
+
{
|
172
|
+
"data": {
|
173
|
+
"id": "1",
|
174
|
+
"type": "posts",
|
175
|
+
"attributes": {
|
176
|
+
"title": "Advanced JPie Techniques"
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
HTTP/1.1 200 OK
|
182
|
+
Content-Type: application/vnd.api+json
|
183
|
+
|
184
|
+
{
|
185
|
+
"data": {
|
186
|
+
"id": "1",
|
187
|
+
"type": "posts",
|
188
|
+
"attributes": {
|
189
|
+
"title": "Advanced JPie Techniques",
|
190
|
+
"content": "This post explains how to use JPie..."
|
191
|
+
},
|
192
|
+
"meta": {
|
193
|
+
"created_at": "2024-01-15T10:30:00Z",
|
194
|
+
"updated_at": "2024-01-15T11:00:00Z"
|
195
|
+
}
|
196
|
+
},
|
197
|
+
"included": [
|
198
|
+
{
|
199
|
+
"id": "1",
|
200
|
+
"type": "users",
|
201
|
+
"attributes": {
|
202
|
+
"name": "John Doe",
|
203
|
+
"email": "john@example.com"
|
204
|
+
},
|
205
|
+
"meta": {
|
206
|
+
"created_at": "2024-01-10T09:00:00Z",
|
207
|
+
"updated_at": "2024-01-10T09:00:00Z"
|
208
|
+
}
|
209
|
+
},
|
210
|
+
{
|
211
|
+
"id": "1",
|
212
|
+
"type": "comments",
|
213
|
+
"attributes": {
|
214
|
+
"content": "Great post! Very helpful."
|
215
|
+
},
|
216
|
+
"meta": {
|
217
|
+
"created_at": "2024-01-15T11:00:00Z",
|
218
|
+
"updated_at": "2024-01-15T11:00:00Z"
|
219
|
+
}
|
220
|
+
}
|
221
|
+
]
|
222
|
+
}
|
223
|
+
```
|
224
|
+
|
225
|
+
### Single Include - Post with User
|
226
|
+
```http
|
227
|
+
GET /posts/1?include=user
|
228
|
+
Accept: application/vnd.api+json
|
229
|
+
|
230
|
+
HTTP/1.1 200 OK
|
231
|
+
Content-Type: application/vnd.api+json
|
232
|
+
|
233
|
+
{
|
234
|
+
"data": {
|
235
|
+
"id": "1",
|
236
|
+
"type": "posts",
|
237
|
+
"attributes": {
|
238
|
+
"title": "Getting Started with JPie",
|
239
|
+
"content": "This post explains how to use JPie..."
|
240
|
+
},
|
241
|
+
"meta": {
|
242
|
+
"created_at": "2024-01-15T10:30:00Z",
|
243
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
244
|
+
}
|
245
|
+
},
|
246
|
+
"included": [
|
247
|
+
{
|
248
|
+
"id": "1",
|
249
|
+
"type": "users",
|
250
|
+
"attributes": {
|
251
|
+
"name": "John Doe",
|
252
|
+
"email": "john@example.com"
|
253
|
+
},
|
254
|
+
"meta": {
|
255
|
+
"created_at": "2024-01-10T09:00:00Z",
|
256
|
+
"updated_at": "2024-01-10T09:00:00Z"
|
257
|
+
}
|
258
|
+
}
|
259
|
+
]
|
260
|
+
}
|
261
|
+
```
|
262
|
+
|
263
|
+
### Multiple Includes - Post with User and Comments
|
264
|
+
```http
|
265
|
+
GET /posts/1?include=user,comments
|
266
|
+
Accept: application/vnd.api+json
|
267
|
+
|
268
|
+
HTTP/1.1 200 OK
|
269
|
+
Content-Type: application/vnd.api+json
|
270
|
+
|
271
|
+
{
|
272
|
+
"data": {
|
273
|
+
"id": "1",
|
274
|
+
"type": "posts",
|
275
|
+
"attributes": {
|
276
|
+
"title": "Getting Started with JPie",
|
277
|
+
"content": "This post explains how to use JPie..."
|
278
|
+
},
|
279
|
+
"meta": {
|
280
|
+
"created_at": "2024-01-15T10:30:00Z",
|
281
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
282
|
+
}
|
283
|
+
},
|
284
|
+
"included": [
|
285
|
+
{
|
286
|
+
"id": "1",
|
287
|
+
"type": "users",
|
288
|
+
"attributes": {
|
289
|
+
"name": "John Doe",
|
290
|
+
"email": "john@example.com"
|
291
|
+
},
|
292
|
+
"meta": {
|
293
|
+
"created_at": "2024-01-10T09:00:00Z",
|
294
|
+
"updated_at": "2024-01-10T09:00:00Z"
|
295
|
+
}
|
296
|
+
},
|
297
|
+
{
|
298
|
+
"id": "1",
|
299
|
+
"type": "comments",
|
300
|
+
"attributes": {
|
301
|
+
"content": "Great post! Very helpful."
|
302
|
+
},
|
303
|
+
"meta": {
|
304
|
+
"created_at": "2024-01-15T11:00:00Z",
|
305
|
+
"updated_at": "2024-01-15T11:00:00Z"
|
306
|
+
}
|
307
|
+
},
|
308
|
+
{
|
309
|
+
"id": "2",
|
310
|
+
"type": "comments",
|
311
|
+
"attributes": {
|
312
|
+
"content": "Thanks for sharing this."
|
313
|
+
},
|
314
|
+
"meta": {
|
315
|
+
"created_at": "2024-01-15T12:00:00Z",
|
316
|
+
"updated_at": "2024-01-15T12:00:00Z"
|
317
|
+
}
|
318
|
+
}
|
319
|
+
]
|
320
|
+
}
|
321
|
+
```
|
322
|
+
|
323
|
+
### Nested Includes - Post with User and User's Profile
|
324
|
+
```http
|
325
|
+
GET /posts/1?include=user.profile
|
326
|
+
Accept: application/vnd.api+json
|
327
|
+
|
328
|
+
HTTP/1.1 200 OK
|
329
|
+
Content-Type: application/vnd.api+json
|
330
|
+
|
331
|
+
{
|
332
|
+
"data": {
|
333
|
+
"id": "1",
|
334
|
+
"type": "posts",
|
335
|
+
"attributes": {
|
336
|
+
"title": "Getting Started with JPie",
|
337
|
+
"content": "This post explains how to use JPie..."
|
338
|
+
},
|
339
|
+
"meta": {
|
340
|
+
"created_at": "2024-01-15T10:30:00Z",
|
341
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
342
|
+
}
|
343
|
+
},
|
344
|
+
"included": [
|
345
|
+
{
|
346
|
+
"id": "1",
|
347
|
+
"type": "users",
|
348
|
+
"attributes": {
|
349
|
+
"name": "John Doe",
|
350
|
+
"email": "john@example.com"
|
351
|
+
},
|
352
|
+
"meta": {
|
353
|
+
"created_at": "2024-01-10T09:00:00Z",
|
354
|
+
"updated_at": "2024-01-10T09:00:00Z"
|
355
|
+
}
|
356
|
+
},
|
357
|
+
{
|
358
|
+
"id": "1",
|
359
|
+
"type": "profiles",
|
360
|
+
"attributes": {
|
361
|
+
"bio": "Software developer passionate about clean APIs",
|
362
|
+
"website": "https://johndoe.dev"
|
363
|
+
},
|
364
|
+
"meta": {
|
365
|
+
"created_at": "2024-01-10T09:30:00Z",
|
366
|
+
"updated_at": "2024-01-12T14:00:00Z"
|
367
|
+
}
|
368
|
+
}
|
369
|
+
]
|
370
|
+
}
|
371
|
+
```
|
372
|
+
|
373
|
+
### Complex Nested Includes - Post with Comments and Comment Users
|
374
|
+
```http
|
375
|
+
GET /posts/1?include=comments.user
|
376
|
+
Accept: application/vnd.api+json
|
377
|
+
|
378
|
+
HTTP/1.1 200 OK
|
379
|
+
Content-Type: application/vnd.api+json
|
380
|
+
|
381
|
+
{
|
382
|
+
"data": {
|
383
|
+
"id": "1",
|
384
|
+
"type": "posts",
|
385
|
+
"attributes": {
|
386
|
+
"title": "Getting Started with JPie",
|
387
|
+
"content": "This post explains how to use JPie..."
|
388
|
+
},
|
389
|
+
"meta": {
|
390
|
+
"created_at": "2024-01-15T10:30:00Z",
|
391
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
392
|
+
}
|
393
|
+
},
|
394
|
+
"included": [
|
395
|
+
{
|
396
|
+
"id": "1",
|
397
|
+
"type": "comments",
|
398
|
+
"attributes": {
|
399
|
+
"content": "Great post! Very helpful."
|
400
|
+
},
|
401
|
+
"meta": {
|
402
|
+
"created_at": "2024-01-15T11:00:00Z",
|
403
|
+
"updated_at": "2024-01-15T11:00:00Z"
|
404
|
+
}
|
405
|
+
},
|
406
|
+
{
|
407
|
+
"id": "2",
|
408
|
+
"type": "comments",
|
409
|
+
"attributes": {
|
410
|
+
"content": "Thanks for sharing this."
|
411
|
+
},
|
412
|
+
"meta": {
|
413
|
+
"created_at": "2024-01-15T12:00:00Z",
|
414
|
+
"updated_at": "2024-01-15T12:00:00Z"
|
415
|
+
}
|
416
|
+
},
|
417
|
+
{
|
418
|
+
"id": "1",
|
419
|
+
"type": "users",
|
420
|
+
"attributes": {
|
421
|
+
"name": "John Doe",
|
422
|
+
"email": "john@example.com"
|
423
|
+
},
|
424
|
+
"meta": {
|
425
|
+
"created_at": "2024-01-10T09:00:00Z",
|
426
|
+
"updated_at": "2024-01-10T09:00:00Z"
|
427
|
+
}
|
428
|
+
},
|
429
|
+
{
|
430
|
+
"id": "2",
|
431
|
+
"type": "users",
|
432
|
+
"attributes": {
|
433
|
+
"name": "Jane Smith",
|
434
|
+
"email": "jane@example.com"
|
435
|
+
},
|
436
|
+
"meta": {
|
437
|
+
"created_at": "2024-01-12T08:00:00Z",
|
438
|
+
"updated_at": "2024-01-12T08:00:00Z"
|
439
|
+
}
|
440
|
+
}
|
441
|
+
]
|
442
|
+
}
|
443
|
+
```
|
444
|
+
|
445
|
+
### Through Association - Post with Tags
|
446
|
+
```http
|
447
|
+
GET /posts/1?include=tags
|
448
|
+
Accept: application/vnd.api+json
|
449
|
+
|
450
|
+
HTTP/1.1 200 OK
|
451
|
+
Content-Type: application/vnd.api+json
|
452
|
+
|
453
|
+
{
|
454
|
+
"data": {
|
455
|
+
"id": "1",
|
456
|
+
"type": "posts",
|
457
|
+
"attributes": {
|
458
|
+
"title": "Getting Started with JPie",
|
459
|
+
"content": "This post explains how to use JPie..."
|
460
|
+
},
|
461
|
+
"meta": {
|
462
|
+
"created_at": "2024-01-15T10:30:00Z",
|
463
|
+
"updated_at": "2024-01-15T10:30:00Z"
|
464
|
+
}
|
465
|
+
},
|
466
|
+
"included": [
|
467
|
+
{
|
468
|
+
"id": "1",
|
469
|
+
"type": "tags",
|
470
|
+
"attributes": {
|
471
|
+
"name": "ruby"
|
472
|
+
},
|
473
|
+
"meta": {
|
474
|
+
"created_at": "2024-01-01T00:00:00Z",
|
475
|
+
"updated_at": "2024-01-01T00:00:00Z"
|
476
|
+
}
|
477
|
+
},
|
478
|
+
{
|
479
|
+
"id": "2",
|
480
|
+
"type": "tags",
|
481
|
+
"attributes": {
|
482
|
+
"name": "api"
|
483
|
+
},
|
484
|
+
"meta": {
|
485
|
+
"created_at": "2024-01-01T00:00:00Z",
|
486
|
+
"updated_at": "2024-01-01T00:00:00Z"
|
487
|
+
}
|
488
|
+
}
|
489
|
+
]
|
490
|
+
}
|
491
|
+
```
|