@kids-reporter/api-types 0.0.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.
Files changed (41) hide show
  1. package/dist/index.d.ts +9 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +9 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/openapi.d.ts +43 -0
  6. package/dist/openapi.d.ts.map +1 -0
  7. package/dist/openapi.js +50 -0
  8. package/dist/openapi.js.map +1 -0
  9. package/dist/rest.d.ts +57 -0
  10. package/dist/rest.d.ts.map +1 -0
  11. package/dist/rest.js +26 -0
  12. package/dist/rest.js.map +1 -0
  13. package/dist/schemas/content-feed-queries.d.ts +34 -0
  14. package/dist/schemas/content-feed-queries.d.ts.map +1 -0
  15. package/dist/schemas/content-feed-queries.js +21 -0
  16. package/dist/schemas/content-feed-queries.js.map +1 -0
  17. package/dist/schemas/content-feed-responses.d.ts +192 -0
  18. package/dist/schemas/content-feed-responses.d.ts.map +1 -0
  19. package/dist/schemas/content-feed-responses.js +87 -0
  20. package/dist/schemas/content-feed-responses.js.map +1 -0
  21. package/dist/schemas/content-post-detail.d.ts +313 -0
  22. package/dist/schemas/content-post-detail.d.ts.map +1 -0
  23. package/dist/schemas/content-post-detail.js +196 -0
  24. package/dist/schemas/content-post-detail.js.map +1 -0
  25. package/dist/schemas/content.d.ts +438 -0
  26. package/dist/schemas/content.d.ts.map +1 -0
  27. package/dist/schemas/content.js +722 -0
  28. package/dist/schemas/content.js.map +1 -0
  29. package/dist/schemas/extra-openapi-paths.d.ts +53 -0
  30. package/dist/schemas/extra-openapi-paths.d.ts.map +1 -0
  31. package/dist/schemas/extra-openapi-paths.js +674 -0
  32. package/dist/schemas/extra-openapi-paths.js.map +1 -0
  33. package/dist/schemas/member-essay-answers-has-liked.d.ts +16 -0
  34. package/dist/schemas/member-essay-answers-has-liked.d.ts.map +1 -0
  35. package/dist/schemas/member-essay-answers-has-liked.js +30 -0
  36. package/dist/schemas/member-essay-answers-has-liked.js.map +1 -0
  37. package/dist/schemas/qna.d.ts +145 -0
  38. package/dist/schemas/qna.d.ts.map +1 -0
  39. package/dist/schemas/qna.js +632 -0
  40. package/dist/schemas/qna.js.map +1 -0
  41. package/package.json +36 -0
@@ -0,0 +1,722 @@
1
+ import { extendZodWithOpenApi, OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
2
+ import { z } from 'zod';
3
+ import { RestErrorBodySchema } from '../rest.js';
4
+ import { V1PostDetailBodySchema, V1PostEssayQuestionsBodySchema, V1PostMetaBodySchema, V1PostsEssayAnswersWithLikesResponseSchema, V1ProjectDetailRelatedPostOrderedItemSchema } from './content-post-detail.js';
5
+ extendZodWithOpenApi(z);
6
+ export const registry = new OpenAPIRegistry();
7
+ export const PhotoResizedSchema = z.object({
8
+ small: z.string().default('').openapi({
9
+ example: 'https://kids.twreporter.org/resized/abc-800.webp'
10
+ })
11
+ }).openapi('ResizedPhoto');
12
+ export const PostHeroImageSchema = z.object({
13
+ resized: PhotoResizedSchema
14
+ }).openapi('PostHeroImage');
15
+
16
+ /**
17
+ * Lightweight sub-subcategory shape for **feeds and list payloads** (`PostContentSchema`,
18
+ * e.g. `/v1/posts`, editor picks). Omits sub-subcategory / subcategory slugs on purpose —
19
+ * callers only need labels + category slug for cards. For the **full tree with slugs**
20
+ * (article detail, related-post cards), see `SubSubcategoryFullItemSchema` in
21
+ * `content-post-detail.ts`.
22
+ */
23
+ export const PostSubSubcategorySchema = z.object({
24
+ name: z.string(),
25
+ subcategory: z.object({
26
+ name: z.string(),
27
+ category: z.object({
28
+ slug: z.string(),
29
+ themeColor: z.string().nullable().optional()
30
+ }).nullable().optional()
31
+ }).nullable().optional()
32
+ }).openapi('PostSubSubcategory');
33
+ export const PostContentSchema = z.object({
34
+ title: z.string(),
35
+ slug: z.string(),
36
+ ogDescription: z.string().nullable().optional(),
37
+ heroImage: PostHeroImageSchema.nullable().optional(),
38
+ subSubcategoriesOrdered: z.array(PostSubSubcategorySchema).default([]),
39
+ publishedDate: z.iso.datetime().nullable().optional()
40
+ }).openapi('PostContent');
41
+ export const SubcategoryItemSchema = z.object({
42
+ id: z.union([z.string(), z.number().int()]),
43
+ name: z.string(),
44
+ slug: z.string(),
45
+ category: z.object({
46
+ slug: z.string()
47
+ }).nullable().optional()
48
+ }).openapi('Subcategory');
49
+ export const CallBaodaozaiIntroItemSchema = z.object({
50
+ id: z.union([z.string(), z.number().int()]),
51
+ page: z.string(),
52
+ content: z.string()
53
+ }).openapi('CallBaodaozaiIntro');
54
+ export const EditorPicksSettingItemSchema = z.object({
55
+ id: z.union([z.string(), z.number().int()]),
56
+ editorPicksOfPostsOrdered: z.array(PostContentSchema).default([]),
57
+ editorPicksOfTags: z.array(z.object({
58
+ name: z.string(),
59
+ slug: z.string()
60
+ })).default([]),
61
+ popularKeywordsOrdered: z.array(z.object({
62
+ name: z.string()
63
+ })).default([])
64
+ }).openapi('EditorPicksSetting');
65
+ export const V1PostsQuerySchema = z.object({
66
+ take: z.coerce.number().int().min(1).max(50).optional(),
67
+ skip: z.coerce.number().int().min(0).max(5000).optional(),
68
+ orderBy: z.enum(['publishedDate:desc']).optional()
69
+ });
70
+ export const V1PostsResponseSchema = z.object({
71
+ posts: z.array(PostContentSchema),
72
+ page: z.object({
73
+ take: z.number().int().min(1).max(50),
74
+ skip: z.number().int().min(0)
75
+ })
76
+ });
77
+ registry.registerPath({
78
+ method: 'get',
79
+ path: '/v1/posts',
80
+ tags: ['Posts'],
81
+ description: 'List latest published posts.',
82
+ request: {
83
+ query: V1PostsQuerySchema
84
+ },
85
+ responses: {
86
+ 200: {
87
+ description: 'Success',
88
+ content: {
89
+ 'application/json': {
90
+ schema: V1PostsResponseSchema
91
+ }
92
+ }
93
+ },
94
+ 400: {
95
+ description: 'Bad request',
96
+ content: {
97
+ 'application/json': {
98
+ schema: RestErrorBodySchema
99
+ }
100
+ }
101
+ }
102
+ }
103
+ });
104
+ export const V1SubcategoriesResponseSchema = z.array(SubcategoryItemSchema);
105
+ registry.registerPath({
106
+ method: 'get',
107
+ path: '/v1/subcategories',
108
+ tags: ['Taxonomy'],
109
+ description: 'All subcategories with parent category slug.',
110
+ responses: {
111
+ 200: {
112
+ description: 'Success',
113
+ content: {
114
+ 'application/json': {
115
+ schema: V1SubcategoriesResponseSchema
116
+ }
117
+ }
118
+ }
119
+ }
120
+ });
121
+ export const V1AuthorAvatarPathParamsSchema = z.object({
122
+ slug: z.string().min(1)
123
+ });
124
+ export const V1AuthorAvatarResponseSchema = z.object({
125
+ tiny: z.string()
126
+ }).openapi('AuthorAvatarTiny');
127
+ registry.registerPath({
128
+ method: 'get',
129
+ path: '/v1/authors/by-slug/{slug}/avatar',
130
+ tags: ['Taxonomy'],
131
+ description: 'Author avatar tiny image URL by slug. `tiny` is empty when the author or avatar is missing.',
132
+ request: {
133
+ params: V1AuthorAvatarPathParamsSchema
134
+ },
135
+ responses: {
136
+ 200: {
137
+ description: 'Success',
138
+ content: {
139
+ 'application/json': {
140
+ schema: V1AuthorAvatarResponseSchema
141
+ }
142
+ }
143
+ }
144
+ }
145
+ });
146
+ export const V1PopularKeywordsResponseSchema = z.array(z.object({
147
+ name: z.string()
148
+ }));
149
+ registry.registerPath({
150
+ method: 'get',
151
+ path: '/v1/popular-keywords',
152
+ tags: ['Editor'],
153
+ description: 'Popular keywords from editor picks ordering.',
154
+ responses: {
155
+ 200: {
156
+ description: 'Success',
157
+ content: {
158
+ 'application/json': {
159
+ schema: V1PopularKeywordsResponseSchema
160
+ }
161
+ }
162
+ }
163
+ }
164
+ });
165
+ export const V1CallBaodaozaiIntroPathParamsSchema = z.object({
166
+ page: z.enum(['home', 'all', 'topics', 'news', 'storytelling', 'campus', 'listeningNews', 'classroom'])
167
+ });
168
+ export const V1CallBaodaozaiIntroResponseSchema = CallBaodaozaiIntroItemSchema;
169
+ registry.registerPath({
170
+ method: 'get',
171
+ path: '/v1/call-baodaozai-intros/{page}',
172
+ tags: ['Editor'],
173
+ description: 'Get Call Baodaozai intro content by page.',
174
+ request: {
175
+ params: V1CallBaodaozaiIntroPathParamsSchema
176
+ },
177
+ responses: {
178
+ 200: {
179
+ description: 'Success',
180
+ content: {
181
+ 'application/json': {
182
+ schema: V1CallBaodaozaiIntroResponseSchema
183
+ }
184
+ }
185
+ },
186
+ 400: {
187
+ description: 'Bad request',
188
+ content: {
189
+ 'application/json': {
190
+ schema: RestErrorBodySchema
191
+ }
192
+ }
193
+ },
194
+ 404: {
195
+ description: 'Not found',
196
+ content: {
197
+ 'application/json': {
198
+ schema: RestErrorBodySchema
199
+ }
200
+ }
201
+ }
202
+ }
203
+ });
204
+
205
+ /** Query for `GET /v1/projects`. */
206
+ export const V1ProjectsQuerySchema = z.object({
207
+ take: z.coerce.number().int().min(1).max(50).optional(),
208
+ skip: z.coerce.number().int().min(0).max(5000).optional(),
209
+ orderBy: z.enum(['publishedDate:desc']).optional(),
210
+ includeRelatedPosts: z.union([z.literal('true'), z.literal('false')]).optional().transform(v => v === 'true')
211
+ });
212
+ export const V1ProjectsItemSchema = z.object({
213
+ title: z.string(),
214
+ subtitle: z.string(),
215
+ slug: z.string(),
216
+ ogDescription: z.string().nullable().optional(),
217
+ publishedDate: z.iso.datetime().nullable().optional(),
218
+ heroImage: z.object({
219
+ resized: z.object({
220
+ small: z.string(),
221
+ medium: z.string()
222
+ })
223
+ }).nullable().optional(),
224
+ relatedPostsOrdered: z.array(PostContentSchema).optional()
225
+ }).openapi('ProjectsItem');
226
+ export const V1ProjectsResponseSchema = z.object({
227
+ projects: z.array(V1ProjectsItemSchema),
228
+ projectsCount: z.number().int().min(0)
229
+ });
230
+ registry.registerPath({
231
+ method: 'get',
232
+ path: '/v1/projects',
233
+ tags: ['Projects'],
234
+ description: 'List published projects. Response always includes `projects` and total `projectsCount`. Optional `relatedPostsOrdered` on each item appears only when `includeRelatedPosts=true`.',
235
+ request: {
236
+ query: V1ProjectsQuerySchema
237
+ },
238
+ responses: {
239
+ 200: {
240
+ description: 'Success',
241
+ content: {
242
+ 'application/json': {
243
+ schema: V1ProjectsResponseSchema
244
+ }
245
+ }
246
+ },
247
+ 400: {
248
+ description: 'Bad request',
249
+ content: {
250
+ 'application/json': {
251
+ schema: RestErrorBodySchema
252
+ }
253
+ }
254
+ }
255
+ }
256
+ });
257
+ export const V1EditorPicksSettingsQuerySchema = z.object({
258
+ take: z.coerce.number().int().min(1).max(20).optional().default(5)
259
+ });
260
+ export const V1EditorPicksSettingsResponseSchema = z.array(EditorPicksSettingItemSchema);
261
+ registry.registerPath({
262
+ method: 'get',
263
+ path: '/v1/editor-picks-settings',
264
+ tags: ['Editor'],
265
+ description: 'Editor picks configuration rows.',
266
+ request: {
267
+ query: V1EditorPicksSettingsQuerySchema
268
+ },
269
+ responses: {
270
+ 200: {
271
+ description: 'Success',
272
+ content: {
273
+ 'application/json': {
274
+ schema: V1EditorPicksSettingsResponseSchema
275
+ }
276
+ }
277
+ },
278
+ 400: {
279
+ description: 'Bad request',
280
+ content: {
281
+ 'application/json': {
282
+ schema: RestErrorBodySchema
283
+ }
284
+ }
285
+ }
286
+ }
287
+ });
288
+ export const V1MemberAvatarSchema = z.object({
289
+ id: z.string(),
290
+ fileUrl: z.string()
291
+ }).openapi('MemberAvatar');
292
+ export const V1MemberProfileSchema = z.object({
293
+ id: z.string(),
294
+ name: z.string(),
295
+ email: z.string(),
296
+ nickname: z.string(),
297
+ contactEmail: z.string(),
298
+ twreporter_user_id: z.string(),
299
+ showBaodaozai: z.boolean(),
300
+ essayQuestionCount: z.number().int().nullable().optional(),
301
+ avatar: V1MemberAvatarSchema.nullable().optional(),
302
+ createdAt: z.iso.datetime().nullable().optional()
303
+ }).openapi('MemberProfile');
304
+ export const V1MemberProfileResponseSchema = V1MemberProfileSchema;
305
+ export const V1MemberProfilePatchBodySchema = z.strictObject({
306
+ name: z.string().optional(),
307
+ nickname: z.string().optional(),
308
+ contactEmail: z.string().optional(),
309
+ showBaodaozai: z.boolean().optional(),
310
+ essayQuestionCount: z.number().int().min(0).max(3).optional()
311
+ }).openapi('MemberProfilePatch');
312
+
313
+ /** Successful `POST /auth/access-token` response JSON. */
314
+ export const V1AccessTokenResponseSchema = z.object({
315
+ accessToken: z.string(),
316
+ twreporterUserId: z.string(),
317
+ expiresAt: z.number()
318
+ });
319
+
320
+ /** GET `/v1/members/me/posts-with-answers` query string. */
321
+ export const V1MemberPostsWithAnswersQuerySchema = z.object({
322
+ take: z.coerce.number().int().min(1).max(50).optional().default(5),
323
+ cursor: z.string().optional()
324
+ });
325
+ registry.registerPath({
326
+ method: 'get',
327
+ path: '/v1/members/me',
328
+ tags: ['Members'],
329
+ description: 'Authenticated member profile (Bearer JWT).',
330
+ responses: {
331
+ 200: {
332
+ description: 'Success',
333
+ content: {
334
+ 'application/json': {
335
+ schema: V1MemberProfileResponseSchema
336
+ }
337
+ }
338
+ },
339
+ 401: {
340
+ description: 'Unauthorized',
341
+ content: {
342
+ 'application/json': {
343
+ schema: RestErrorBodySchema
344
+ }
345
+ }
346
+ },
347
+ 404: {
348
+ description: 'Member not found',
349
+ content: {
350
+ 'application/json': {
351
+ schema: RestErrorBodySchema
352
+ }
353
+ }
354
+ }
355
+ }
356
+ });
357
+ registry.registerPath({
358
+ method: 'patch',
359
+ path: '/v1/members/me',
360
+ tags: ['Members'],
361
+ description: 'Update authenticated member profile (Bearer JWT).',
362
+ request: {
363
+ body: {
364
+ content: {
365
+ 'application/json': {
366
+ schema: V1MemberProfilePatchBodySchema
367
+ }
368
+ }
369
+ }
370
+ },
371
+ responses: {
372
+ 200: {
373
+ description: 'Success',
374
+ content: {
375
+ 'application/json': {
376
+ schema: V1MemberProfileResponseSchema
377
+ }
378
+ }
379
+ },
380
+ 400: {
381
+ description: 'Bad request',
382
+ content: {
383
+ 'application/json': {
384
+ schema: RestErrorBodySchema
385
+ }
386
+ }
387
+ },
388
+ 401: {
389
+ description: 'Unauthorized',
390
+ content: {
391
+ 'application/json': {
392
+ schema: RestErrorBodySchema
393
+ }
394
+ }
395
+ },
396
+ 404: {
397
+ description: 'Member not found',
398
+ content: {
399
+ 'application/json': {
400
+ schema: RestErrorBodySchema
401
+ }
402
+ }
403
+ }
404
+ }
405
+ });
406
+ export const V1PostBySlugPathParamsSchema = z.object({
407
+ slug: z.string().min(1)
408
+ });
409
+
410
+ /** Flat query for `GET /v1/posts/by-slug/{slug}` (news-reading order + related-posts filter are fixed server-side). */
411
+ export const V1PostBySlugQuerySchema = z.object({
412
+ take: z.coerce.number().int().min(1).max(50).optional().default(5),
413
+ postEssayQuestionsTake: z.coerce.number().int().min(1).max(50).optional().default(3),
414
+ postChoiceQuestionsTake: z.coerce.number().int().min(1).max(50).optional().default(3)
415
+ });
416
+ export const V1SitemapsQuerySchema = z.object({
417
+ sinceDays: z.coerce.number().int().min(1).max(365).optional().default(60)
418
+ });
419
+ export const V1SitemapEntrySchema = z.object({
420
+ slug: z.string(),
421
+ publishedDate: z.iso.datetime().nullable()
422
+ });
423
+ export const V1SitemapPostsResponseSchema = z.array(V1SitemapEntrySchema);
424
+ export const V1SitemapProjectsResponseSchema = z.array(V1SitemapEntrySchema);
425
+ export const V1ProjectBySlugMetaResponseSchema = z.object({
426
+ publishedDate: z.iso.datetime().optional(),
427
+ ogTitle: z.string(),
428
+ ogDescription: z.string().nullable(),
429
+ ogImage: z.object({
430
+ resized: z.object({
431
+ small: z.string()
432
+ })
433
+ }).nullable()
434
+ });
435
+
436
+ /** Hero image payloads returned by `/v1/projects/by-slug/{slug}` match Prisma-mapper targets. */
437
+ export const V1ProjectDetailPhotoResizedSchema = z.object({
438
+ resized: z.object({
439
+ small: z.string(),
440
+ medium: z.string(),
441
+ large: z.string()
442
+ })
443
+ });
444
+ export const V1ProjectBySlugDetailResponseSchema = z.object({
445
+ title: z.string(),
446
+ titlePosition: z.string().nullable().optional(),
447
+ subtitle: z.string(),
448
+ /** Draft.js JSON etc.; `z.json()` overflows zod-to-openapi union expansion. */
449
+ content: z.unknown().nullable().optional(),
450
+ credits: z.unknown().nullable().optional(),
451
+ publishedDate: z.iso.datetime().optional(),
452
+ heroImage: V1ProjectDetailPhotoResizedSchema.optional(),
453
+ mobileHeroImage: V1ProjectDetailPhotoResizedSchema.optional(),
454
+ relatedPostsOrdered: z.array(V1ProjectDetailRelatedPostOrderedItemSchema)
455
+ });
456
+ export const V1ProjectRelatedPostsCountResponseSchema = z.object({
457
+ relatedPostsCount: z.number().int().min(0)
458
+ });
459
+ export const V1AuthorPostsCountResponseSchema = z.object({
460
+ postsCount: z.number().int().min(0)
461
+ });
462
+ registry.registerPath({
463
+ method: 'get',
464
+ path: '/v1/sitemaps/posts',
465
+ tags: ['Sitemaps'],
466
+ description: 'Post slugs + published dates for sitemap (public posts only). Query `sinceDays` (1–365, default 60): include posts with `publishedDate` on/after start of day `now - sinceDays`.',
467
+ request: {
468
+ query: V1SitemapsQuerySchema
469
+ },
470
+ responses: {
471
+ 200: {
472
+ description: 'Success',
473
+ content: {
474
+ 'application/json': {
475
+ schema: V1SitemapPostsResponseSchema
476
+ }
477
+ }
478
+ },
479
+ 400: {
480
+ description: 'Bad request',
481
+ content: {
482
+ 'application/json': {
483
+ schema: RestErrorBodySchema
484
+ }
485
+ }
486
+ }
487
+ }
488
+ });
489
+ registry.registerPath({
490
+ method: 'get',
491
+ path: '/v1/sitemaps/projects',
492
+ tags: ['Sitemaps'],
493
+ description: 'Published project slugs + dates for sitemap. Query `sinceDays` (1–365, default 60): include projects with `publishedDate` on/after start of day `now - sinceDays`.',
494
+ request: {
495
+ query: V1SitemapsQuerySchema
496
+ },
497
+ responses: {
498
+ 200: {
499
+ description: 'Success',
500
+ content: {
501
+ 'application/json': {
502
+ schema: V1SitemapProjectsResponseSchema
503
+ }
504
+ }
505
+ },
506
+ 400: {
507
+ description: 'Bad request',
508
+ content: {
509
+ 'application/json': {
510
+ schema: RestErrorBodySchema
511
+ }
512
+ }
513
+ }
514
+ }
515
+ });
516
+ registry.registerPath({
517
+ method: 'get',
518
+ path: '/v1/projects/by-slug/{slug}',
519
+ tags: ['Projects'],
520
+ description: 'Published project detail for topic page (matches GraphQL `GetProject`).',
521
+ request: {
522
+ params: V1PostBySlugPathParamsSchema
523
+ },
524
+ responses: {
525
+ 200: {
526
+ description: 'Success',
527
+ content: {
528
+ 'application/json': {
529
+ schema: V1ProjectBySlugDetailResponseSchema
530
+ }
531
+ }
532
+ },
533
+ 404: {
534
+ description: 'Not found',
535
+ content: {
536
+ 'application/json': {
537
+ schema: RestErrorBodySchema
538
+ }
539
+ }
540
+ }
541
+ }
542
+ });
543
+ registry.registerPath({
544
+ method: 'get',
545
+ path: '/v1/projects/by-slug/{slug}/meta',
546
+ tags: ['Projects'],
547
+ description: 'Published project OG metadata (matches GraphQL `GetProjectMeta`).',
548
+ request: {
549
+ params: V1PostBySlugPathParamsSchema
550
+ },
551
+ responses: {
552
+ 200: {
553
+ description: 'Success',
554
+ content: {
555
+ 'application/json': {
556
+ schema: V1ProjectBySlugMetaResponseSchema
557
+ }
558
+ }
559
+ },
560
+ 404: {
561
+ description: 'Not found',
562
+ content: {
563
+ 'application/json': {
564
+ schema: RestErrorBodySchema
565
+ }
566
+ }
567
+ }
568
+ }
569
+ });
570
+ registry.registerPath({
571
+ method: 'get',
572
+ path: '/v1/projects/by-slug/{slug}/related-posts-count',
573
+ tags: ['Projects'],
574
+ description: 'Count of public posts linked to a published project (matches GraphQL `relatedPostsCount` on project).',
575
+ request: {
576
+ params: V1PostBySlugPathParamsSchema
577
+ },
578
+ responses: {
579
+ 200: {
580
+ description: 'Success',
581
+ content: {
582
+ 'application/json': {
583
+ schema: V1ProjectRelatedPostsCountResponseSchema
584
+ }
585
+ }
586
+ },
587
+ 404: {
588
+ description: 'Not found',
589
+ content: {
590
+ 'application/json': {
591
+ schema: RestErrorBodySchema
592
+ }
593
+ }
594
+ }
595
+ }
596
+ });
597
+ export const V1PostsEssayAnswersWithLikesQuerySchema = z.object({
598
+ take: z.coerce.number().int().min(1).max(50).optional().default(12),
599
+ skip: z.coerce.number().int().min(0).max(5000).optional().default(0),
600
+ orderBy: z.enum(['publishedDate:desc']).optional().default('publishedDate:desc'),
601
+ answerTake: z.coerce.number().int().min(1).max(50).optional().default(10),
602
+ answerOrderBy: z.enum(['likesCount:desc', 'createdAt:desc']).optional().default('likesCount:desc')
603
+ });
604
+ registry.registerPath({
605
+ method: 'get',
606
+ path: '/v1/posts/by-slug/{slug}',
607
+ tags: ['Posts'],
608
+ description: 'Single post article payload (matches GraphQL `GetPost`). Flat query: `take`, `postEssayQuestionsTake`, `postChoiceQuestionsTake` (1–50 each, defaults 5/3/3). News-reading item order and nested related-posts filter are fixed server-side.',
609
+ request: {
610
+ params: V1PostBySlugPathParamsSchema,
611
+ query: V1PostBySlugQuerySchema
612
+ },
613
+ responses: {
614
+ 200: {
615
+ description: 'Success',
616
+ content: {
617
+ 'application/json': {
618
+ schema: V1PostDetailBodySchema
619
+ }
620
+ }
621
+ },
622
+ 400: {
623
+ description: 'Bad request',
624
+ content: {
625
+ 'application/json': {
626
+ schema: RestErrorBodySchema
627
+ }
628
+ }
629
+ },
630
+ 404: {
631
+ description: 'Not found',
632
+ content: {
633
+ 'application/json': {
634
+ schema: RestErrorBodySchema
635
+ }
636
+ }
637
+ }
638
+ }
639
+ });
640
+ registry.registerPath({
641
+ method: 'get',
642
+ path: '/v1/posts/by-slug/{slug}/meta',
643
+ tags: ['Posts'],
644
+ description: 'Post SEO / Open Graph metadata (matches GraphQL `GetPostMeta`).',
645
+ request: {
646
+ params: V1PostBySlugPathParamsSchema
647
+ },
648
+ responses: {
649
+ 200: {
650
+ description: 'Success',
651
+ content: {
652
+ 'application/json': {
653
+ schema: V1PostMetaBodySchema
654
+ }
655
+ }
656
+ },
657
+ 404: {
658
+ description: 'Not found',
659
+ content: {
660
+ 'application/json': {
661
+ schema: RestErrorBodySchema
662
+ }
663
+ }
664
+ }
665
+ }
666
+ });
667
+ registry.registerPath({
668
+ method: 'get',
669
+ path: '/v1/posts/by-slug/{slug}/essay-questions',
670
+ tags: ['Posts'],
671
+ description: 'Post card plus essay questions (matches GraphQL `GetPostEssayQuestions`).',
672
+ request: {
673
+ params: V1PostBySlugPathParamsSchema
674
+ },
675
+ responses: {
676
+ 200: {
677
+ description: 'Success',
678
+ content: {
679
+ 'application/json': {
680
+ schema: V1PostEssayQuestionsBodySchema
681
+ }
682
+ }
683
+ },
684
+ 404: {
685
+ description: 'Not found',
686
+ content: {
687
+ 'application/json': {
688
+ schema: RestErrorBodySchema
689
+ }
690
+ }
691
+ }
692
+ }
693
+ });
694
+ registry.registerPath({
695
+ method: 'get',
696
+ path: '/v1/posts/essay-answers-with-likes',
697
+ tags: ['Posts'],
698
+ description: 'Paged posts with nested essay answers and member avatars (matches GraphQL `GetPostsEssayAnswersWithLikes`). Flat query: `take`, `skip`, `orderBy` (`publishedDate:desc` only), `answerTake`, `answerOrderBy` (`likesCount:desc` | `createdAt:desc`). Post filter (posts with answered essay questions) is fixed server-side.',
699
+ request: {
700
+ query: V1PostsEssayAnswersWithLikesQuerySchema
701
+ },
702
+ responses: {
703
+ 200: {
704
+ description: 'Success',
705
+ content: {
706
+ 'application/json': {
707
+ schema: V1PostsEssayAnswersWithLikesResponseSchema
708
+ }
709
+ }
710
+ },
711
+ 400: {
712
+ description: 'Bad request',
713
+ content: {
714
+ 'application/json': {
715
+ schema: RestErrorBodySchema
716
+ }
717
+ }
718
+ }
719
+ }
720
+ });
721
+ export * from './content-post-detail.js';
722
+ //# sourceMappingURL=content.js.map