@twreporter-academy/api-types 0.0.10 → 0.0.12

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.
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from './schemas/activity.js';
5
5
  export * from './schemas/course.js';
6
6
  export * from './schemas/lesson-progress.js';
7
7
  export * from './schemas/member.js';
8
+ export * from './schemas/photo.js';
8
9
  export * from './schemas/post.js';
9
10
  export * from './schemas/tag.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export * from './schemas/activity.js';
5
5
  export * from './schemas/course.js';
6
6
  export * from './schemas/lesson-progress.js';
7
7
  export * from './schemas/member.js';
8
+ export * from './schemas/photo.js';
8
9
  export * from './schemas/post.js';
9
10
  export * from './schemas/tag.js';
10
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export * from './api-variables.js'\nexport * from './openapi.js'\nexport * from './rest.js'\nexport * from './schemas/activity.js'\nexport * from './schemas/course.js'\nexport * from './schemas/lesson-progress.js'\nexport * from './schemas/member.js'\nexport * from './schemas/post.js'\nexport * from './schemas/tag.js'\n"],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,uBAAuB;AACrC,cAAc,qBAAqB;AACnC,cAAc,8BAA8B;AAC5C,cAAc,qBAAqB;AACnC,cAAc,mBAAmB;AACjC,cAAc,kBAAkB","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export * from './api-variables.js'\nexport * from './openapi.js'\nexport * from './rest.js'\nexport * from './schemas/activity.js'\nexport * from './schemas/course.js'\nexport * from './schemas/lesson-progress.js'\nexport * from './schemas/member.js'\nexport * from './schemas/photo.js'\nexport * from './schemas/post.js'\nexport * from './schemas/tag.js'\n"],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,uBAAuB;AACrC,cAAc,qBAAqB;AACnC,cAAc,8BAA8B;AAC5C,cAAc,qBAAqB;AACnC,cAAc,oBAAoB;AAClC,cAAc,mBAAmB;AACjC,cAAc,kBAAkB","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export declare const CloudflareStreamVideoSchema: z.ZodObject<{
3
+ title: z.ZodString;
4
+ videoId: z.ZodNullable<z.ZodString>;
5
+ }, z.core.$strip>;
6
+ //# sourceMappingURL=cloudflare-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-stream.d.ts","sourceRoot":"","sources":["../../src/schemas/cloudflare-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,2BAA2B;;;iBAGtC,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export const CloudflareStreamVideoSchema = z.object({
3
+ title: z.string(),
4
+ videoId: z.string().nullable()
5
+ });
6
+ //# sourceMappingURL=cloudflare-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-stream.js","names":["z","CloudflareStreamVideoSchema","object","title","string","videoId","nullable"],"sources":["../../src/schemas/cloudflare-stream.ts"],"sourcesContent":["import { z } from 'zod'\n\nexport const CloudflareStreamVideoSchema = z.object({\n title: z.string(),\n videoId: z.string().nullable(),\n})\n"],"mappings":"AAAA,SAASA,CAAC,QAAQ,KAAK;AAEvB,OAAO,MAAMC,2BAA2B,GAAGD,CAAC,CAACE,MAAM,CAAC;EAClDC,KAAK,EAAEH,CAAC,CAACI,MAAM,CAAC,CAAC;EACjBC,OAAO,EAAEL,CAAC,CAACI,MAAM,CAAC,CAAC,CAACE,QAAQ,CAAC;AAC/B,CAAC,CAAC","ignoreList":[]}
@@ -9,7 +9,10 @@ export declare const V1CourseBySlugMetaResponseSchema: z.ZodObject<{
9
9
  ogDescription: z.ZodString;
10
10
  ogImage: z.ZodNullable<z.ZodObject<{
11
11
  resized: z.ZodObject<{
12
+ tiny: z.ZodString;
12
13
  small: z.ZodString;
14
+ medium: z.ZodString;
15
+ large: z.ZodString;
13
16
  }, z.core.$strip>;
14
17
  }, z.core.$strip>>;
15
18
  }, z.core.$strip>;
@@ -26,6 +29,11 @@ export declare const V1CourseLessonSchema: z.ZodObject<{
26
29
  lastWatchedAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
27
30
  }, z.core.$strip>>>;
28
31
  }, z.core.$strip>;
32
+ export declare const V1CourseLessonMetaSchema: z.ZodObject<{
33
+ order: z.ZodNullable<z.ZodNumber>;
34
+ title: z.ZodString;
35
+ duration: z.ZodNullable<z.ZodNumber>;
36
+ }, z.core.$strip>;
29
37
  export declare const V1CourseInstructorSchema: z.ZodObject<{
30
38
  id: z.ZodString;
31
39
  slug: z.ZodString;
@@ -75,17 +83,23 @@ export declare const V1CoursesListResponseSchema: z.ZodObject<{
75
83
  }>>;
76
84
  }, z.core.$strip>>;
77
85
  }, z.core.$strip>;
78
- export declare const V1CourseBySlugResponseSchema: z.ZodObject<{
86
+ export declare const V1CourseTagSchema: z.ZodObject<{
87
+ slug: z.ZodString;
88
+ name: z.ZodString;
89
+ }, z.core.$strip>;
90
+ export declare const V1ClassroomBySlugResponseSchema: z.ZodObject<{
79
91
  slug: z.ZodString;
80
92
  title: z.ZodString;
81
93
  subtitle: z.ZodString;
82
94
  summary: z.ZodString;
83
- description: z.ZodNullable<z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
84
95
  status: z.ZodEnum<{
85
96
  published: "published";
86
97
  coming_soon: "coming_soon";
87
98
  }>;
88
- tags: z.ZodArray<z.ZodString>;
99
+ tags: z.ZodArray<z.ZodObject<{
100
+ slug: z.ZodString;
101
+ name: z.ZodString;
102
+ }, z.core.$strip>>;
89
103
  previewVideoId: z.ZodNullable<z.ZodString>;
90
104
  lessons: z.ZodArray<z.ZodObject<{
91
105
  id: z.ZodString;
@@ -122,4 +136,46 @@ export declare const V1CourseBySlugResponseSchema: z.ZodObject<{
122
136
  url: z.ZodString;
123
137
  }, z.core.$strip>>;
124
138
  }, z.core.$strip>;
139
+ export declare const V1CourseBySlugResponseSchema: z.ZodObject<{
140
+ slug: z.ZodString;
141
+ title: z.ZodString;
142
+ subtitle: z.ZodString;
143
+ summary: z.ZodString;
144
+ launchAt: z.ZodNullable<z.ZodISODateTime>;
145
+ description: z.ZodNullable<z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
146
+ status: z.ZodEnum<{
147
+ published: "published";
148
+ coming_soon: "coming_soon";
149
+ }>;
150
+ tags: z.ZodArray<z.ZodObject<{
151
+ slug: z.ZodString;
152
+ name: z.ZodString;
153
+ }, z.core.$strip>>;
154
+ trialVideos: z.ZodNullable<z.ZodArray<z.ZodObject<{
155
+ title: z.ZodString;
156
+ videoId: z.ZodNullable<z.ZodString>;
157
+ }, z.core.$strip>>>;
158
+ lessonsMeta: z.ZodArray<z.ZodObject<{
159
+ order: z.ZodNullable<z.ZodNumber>;
160
+ title: z.ZodString;
161
+ duration: z.ZodNullable<z.ZodNumber>;
162
+ }, z.core.$strip>>;
163
+ instructors: z.ZodArray<z.ZodObject<{
164
+ id: z.ZodString;
165
+ slug: z.ZodString;
166
+ name: z.ZodString;
167
+ title: z.ZodString;
168
+ bio: z.ZodString;
169
+ avatarUrl: z.ZodNullable<z.ZodString>;
170
+ }, z.core.$strip>>;
171
+ heroImage: z.ZodNullable<z.ZodObject<{
172
+ title: z.ZodString;
173
+ resized: z.ZodObject<{
174
+ tiny: z.ZodString;
175
+ small: z.ZodString;
176
+ medium: z.ZodString;
177
+ large: z.ZodString;
178
+ }, z.core.$strip>;
179
+ }, z.core.$strip>>;
180
+ }, z.core.$strip>;
125
181
  //# sourceMappingURL=course.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"course.d.ts","sourceRoot":"","sources":["../../src/schemas/course.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,OAAO,EAAE,GACT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE3B,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAO/C,CAAA;AAEF,eAAO,MAAM,4BAA4B;;iBAEvC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;iBAI3C,CAAA;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;iBAcP,CAAA;AAE1B,eAAO,MAAM,wBAAwB;;;;;;;iBASP,CAAA;AAE9B,eAAO,MAAM,sBAAsB;;;;;iBAQP,CAAA;AAE5B,eAAO,MAAM,4BAA4B;;;;;;iBAQP,CAAA;AAElC,eAAO,MAAM,oBAAoB;;;EAAuC,CAAA;AAExE,eAAO,MAAM,yBAAyB;;;EAAyB,CAAA;AAE/D,eAAO,MAAM,wBAAwB;;;;;;;;iBAOP,CAAA;AAE9B,eAAO,MAAM,2BAA2B;;;;;;;;;;iBAIP,CAAA;AAEjC,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBf,CAAA"}
1
+ {"version":3,"file":"course.d.ts","sourceRoot":"","sources":["../../src/schemas/course.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AASvB,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,OAAO,EAAE,GACT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE3B,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAO/C,CAAA;AAEF,eAAO,MAAM,4BAA4B;;iBAEvC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;iBAI3C,CAAA;AAEF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;iBAcP,CAAA;AAE1B,eAAO,MAAM,wBAAwB;;;;iBAQP,CAAA;AAE9B,eAAO,MAAM,wBAAwB;;;;;;;iBASP,CAAA;AAE9B,eAAO,MAAM,sBAAsB;;;;;iBAQP,CAAA;AAE5B,eAAO,MAAM,4BAA4B;;;;;;iBAQP,CAAA;AAElC,eAAO,MAAM,oBAAoB;;;EAAuC,CAAA;AAExE,eAAO,MAAM,yBAAyB;;;EAAyB,CAAA;AAE/D,eAAO,MAAM,wBAAwB;;;;;;;;iBAOP,CAAA;AAE9B,eAAO,MAAM,2BAA2B;;;;;;;;;;iBAIP,CAAA;AAEjC,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgBf,CAAA;AAE7B,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBf,CAAA"}
@@ -1,6 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import { RestErrorBodySchema } from '../rest.js';
3
+ import { CloudflareStreamVideoSchema } from './cloudflare-stream.js';
3
4
  import { V1LessonProgressSchema } from './lesson-progress.js';
5
+ import { PhotoSchema } from './photo.js';
4
6
  import { registry } from './registry.js';
5
7
  import { CourseThumbnailSchema } from './tag.js';
6
8
  export const JsonValueSchema = z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(z.unknown()), z.record(z.string(), z.unknown())]);
@@ -25,6 +27,13 @@ export const V1CourseLessonSchema = z.object({
25
27
  /** Present when request includes a valid member JWT; null when no progress record */
26
28
  progress: V1LessonProgressSchema.nullable().optional()
27
29
  }).openapi('CourseLesson');
30
+ export const V1CourseLessonMetaSchema = z.object({
31
+ order: z.number().int().nullable(),
32
+ title: z.string(),
33
+ /** Video length in seconds (from CMS); null when not yet set */
34
+ duration: z.number().int().nullable()
35
+ /** CMS 免費試看 flag; playback access is decided by user role (out of scope here) */
36
+ }).openapi('CourseLessonMeta');
28
37
  export const V1CourseInstructorSchema = z.object({
29
38
  id: z.string(),
30
39
  slug: z.string(),
@@ -58,21 +67,40 @@ export const V1HeaderCourseItemSchema = z.object({
58
67
  export const V1CoursesListResponseSchema = z.object({
59
68
  courses: z.array(V1HeaderCourseItemSchema)
60
69
  }).openapi('CoursesListResponse');
61
- export const V1CourseBySlugResponseSchema = z.object({
70
+ export const V1CourseTagSchema = z.object({
71
+ slug: z.string(),
72
+ name: z.string()
73
+ });
74
+ export const V1ClassroomBySlugResponseSchema = z.object({
62
75
  slug: z.string(),
63
76
  title: z.string(),
64
77
  subtitle: z.string(),
65
78
  summary: z.string(),
66
- description: JsonValueSchema.nullable(),
67
79
  /** published: full payload; coming_soon: lessons/resources/furtherReading/previewVideoId stripped */
68
80
  status: V1CourseStatusSchema,
69
- tags: z.array(z.string()),
81
+ tags: z.array(V1CourseTagSchema),
70
82
  /** Trial/preview stream only; null when unconfigured or course is coming_soon */
71
83
  previewVideoId: z.string().nullable(),
72
84
  lessons: z.array(V1CourseLessonSchema),
73
85
  instructors: z.array(V1CourseInstructorSchema),
74
86
  resources: z.array(V1CourseResourceSchema),
75
87
  furtherReading: z.array(V1CourseFurtherReadingSchema)
88
+ }).openapi('ClassroomDetail');
89
+ export const V1CourseBySlugResponseSchema = z.object({
90
+ slug: z.string(),
91
+ title: z.string(),
92
+ subtitle: z.string(),
93
+ summary: z.string(),
94
+ launchAt: z.iso.datetime().nullable(),
95
+ description: JsonValueSchema.nullable(),
96
+ /** published: full payload; coming_soon: lessons/resources/furtherReading/previewVideoId stripped */
97
+ status: V1CourseStatusSchema,
98
+ tags: z.array(V1CourseTagSchema),
99
+ /** Trial/preview stream only; null when unconfigured or course is coming_soon */
100
+ trialVideos: z.array(CloudflareStreamVideoSchema).nullable(),
101
+ lessonsMeta: z.array(V1CourseLessonMetaSchema),
102
+ instructors: z.array(V1CourseInstructorSchema),
103
+ heroImage: PhotoSchema.nullable()
76
104
  }).openapi('CourseDetail');
77
105
 
78
106
  // --- OpenAPI path registration ---
@@ -1 +1 @@
1
- {"version":3,"file":"course.js","names":["z","RestErrorBodySchema","V1LessonProgressSchema","registry","CourseThumbnailSchema","JsonValueSchema","union","string","number","boolean","null","array","unknown","record","V1CourseSlugPathParamsSchema","object","slug","min","max","V1CourseBySlugMetaResponseSchema","ogTitle","ogDescription","ogImage","nullable","V1CourseLessonSchema","id","order","int","title","videoId","durationSeconds","isFree","progress","optional","openapi","V1CourseInstructorSchema","name","bio","avatarUrl","V1CourseResourceSchema","description","downloadUrl","V1CourseFurtherReadingSchema","excerpt","thumbnailUrl","url","V1CourseStatusSchema","enum","V1HeaderCourseBadgeSchema","V1HeaderCourseItemSchema","subtitle","badge","V1CoursesListResponseSchema","courses","V1CourseBySlugResponseSchema","summary","status","tags","previewVideoId","lessons","instructors","resources","furtherReading","internalServerErrorResponse","content","schema","registerPath","method","path","responses","request","params"],"sources":["../../src/schemas/course.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { RestErrorBodySchema } from '../rest.js'\nimport { V1LessonProgressSchema } from './lesson-progress.js'\nimport { registry } from './registry.js'\nimport { CourseThumbnailSchema } from './tag.js'\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | unknown[]\n | Record<string, unknown>\n\nexport const JsonValueSchema: z.ZodType<JsonValue> = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.array(z.unknown()),\n z.record(z.string(), z.unknown()),\n])\n\nexport const V1CourseSlugPathParamsSchema = z.object({\n slug: z.string().min(1).max(200),\n})\n\nexport const V1CourseBySlugMetaResponseSchema = z.object({\n ogTitle: z.string(),\n ogDescription: z.string(),\n ogImage: CourseThumbnailSchema.nullable(),\n})\n\nexport const V1CourseLessonSchema = z\n .object({\n id: z.string(),\n order: z.number().int(),\n title: z.string(),\n /** Cloudflare stream id for this lesson; null when not yet set */\n videoId: z.string().nullable(),\n /** Video length in seconds (from CMS); null when not yet set */\n durationSeconds: z.number().int().nullable(),\n /** CMS 免費試看 flag; playback access is decided by user role (out of scope here) */\n isFree: z.boolean(),\n /** Present when request includes a valid member JWT; null when no progress record */\n progress: V1LessonProgressSchema.nullable().optional(),\n })\n .openapi('CourseLesson')\n\nexport const V1CourseInstructorSchema = z\n .object({\n id: z.string(),\n slug: z.string(),\n name: z.string(),\n title: z.string(),\n bio: z.string(),\n avatarUrl: z.string().nullable(),\n })\n .openapi('CourseInstructor')\n\nexport const V1CourseResourceSchema = z\n .object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n /** GCS file URL; empty when no PDF uploaded */\n downloadUrl: z.string(),\n })\n .openapi('CourseResource')\n\nexport const V1CourseFurtherReadingSchema = z\n .object({\n id: z.string(),\n title: z.string(),\n excerpt: z.string(),\n thumbnailUrl: z.string().nullable(),\n url: z.string(),\n })\n .openapi('CourseFurtherReading')\n\nexport const V1CourseStatusSchema = z.enum(['published', 'coming_soon'])\n\nexport const V1HeaderCourseBadgeSchema = z.enum(['new', 'wip'])\n\nexport const V1HeaderCourseItemSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n badge: V1HeaderCourseBadgeSchema.optional(),\n })\n .openapi('HeaderCourseItem')\n\nexport const V1CoursesListResponseSchema = z\n .object({\n courses: z.array(V1HeaderCourseItemSchema),\n })\n .openapi('CoursesListResponse')\n\nexport const V1CourseBySlugResponseSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n summary: z.string(),\n description: JsonValueSchema.nullable(),\n /** published: full payload; coming_soon: lessons/resources/furtherReading/previewVideoId stripped */\n status: V1CourseStatusSchema,\n tags: z.array(z.string()),\n /** Trial/preview stream only; null when unconfigured or course is coming_soon */\n previewVideoId: z.string().nullable(),\n lessons: z.array(V1CourseLessonSchema),\n instructors: z.array(V1CourseInstructorSchema),\n resources: z.array(V1CourseResourceSchema),\n furtherReading: z.array(V1CourseFurtherReadingSchema),\n })\n .openapi('CourseDetail')\n\n// --- OpenAPI path registration ---\n\nconst internalServerErrorResponse = {\n 500: {\n description: 'Internal server error',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/courses',\n tags: ['Courses'],\n description: 'Header course list.',\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1CoursesListResponseSchema },\n },\n },\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/courses/{slug}/meta',\n tags: ['Courses'],\n description: 'OG metadata for a course page.',\n request: { params: V1CourseSlugPathParamsSchema },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1CourseBySlugMetaResponseSchema },\n },\n },\n 400: {\n description: 'Bad request',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 404: {\n description: 'Course not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/courses/{slug}',\n tags: ['Courses'],\n description:\n 'Full course detail for the classroom page. When status is coming_soon, lessons, resources, furtherReading, and previewVideoId are empty/null while title, description, tags, and instructors remain visible.',\n request: { params: V1CourseSlugPathParamsSchema },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1CourseBySlugResponseSchema },\n },\n },\n 400: {\n description: 'Bad request',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 404: {\n description: 'Course not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"course.js","names":["z","RestErrorBodySchema","CloudflareStreamVideoSchema","V1LessonProgressSchema","PhotoSchema","registry","CourseThumbnailSchema","JsonValueSchema","union","string","number","boolean","null","array","unknown","record","V1CourseSlugPathParamsSchema","object","slug","min","max","V1CourseBySlugMetaResponseSchema","ogTitle","ogDescription","ogImage","nullable","V1CourseLessonSchema","id","order","int","title","videoId","durationSeconds","isFree","progress","optional","openapi","V1CourseLessonMetaSchema","duration","V1CourseInstructorSchema","name","bio","avatarUrl","V1CourseResourceSchema","description","downloadUrl","V1CourseFurtherReadingSchema","excerpt","thumbnailUrl","url","V1CourseStatusSchema","enum","V1HeaderCourseBadgeSchema","V1HeaderCourseItemSchema","subtitle","badge","V1CoursesListResponseSchema","courses","V1CourseTagSchema","V1ClassroomBySlugResponseSchema","summary","status","tags","previewVideoId","lessons","instructors","resources","furtherReading","V1CourseBySlugResponseSchema","launchAt","iso","datetime","trialVideos","lessonsMeta","heroImage","internalServerErrorResponse","content","schema","registerPath","method","path","responses","request","params"],"sources":["../../src/schemas/course.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { RestErrorBodySchema } from '../rest.js'\nimport { CloudflareStreamVideoSchema } from './cloudflare-stream.js'\nimport { V1LessonProgressSchema } from './lesson-progress.js'\nimport { PhotoSchema } from './photo.js'\nimport { registry } from './registry.js'\nimport { CourseThumbnailSchema } from './tag.js'\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | unknown[]\n | Record<string, unknown>\n\nexport const JsonValueSchema: z.ZodType<JsonValue> = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.array(z.unknown()),\n z.record(z.string(), z.unknown()),\n])\n\nexport const V1CourseSlugPathParamsSchema = z.object({\n slug: z.string().min(1).max(200),\n})\n\nexport const V1CourseBySlugMetaResponseSchema = z.object({\n ogTitle: z.string(),\n ogDescription: z.string(),\n ogImage: CourseThumbnailSchema.nullable(),\n})\n\nexport const V1CourseLessonSchema = z\n .object({\n id: z.string(),\n order: z.number().int(),\n title: z.string(),\n /** Cloudflare stream id for this lesson; null when not yet set */\n videoId: z.string().nullable(),\n /** Video length in seconds (from CMS); null when not yet set */\n durationSeconds: z.number().int().nullable(),\n /** CMS 免費試看 flag; playback access is decided by user role (out of scope here) */\n isFree: z.boolean(),\n /** Present when request includes a valid member JWT; null when no progress record */\n progress: V1LessonProgressSchema.nullable().optional(),\n })\n .openapi('CourseLesson')\n\nexport const V1CourseLessonMetaSchema = z\n .object({\n order: z.number().int().nullable(),\n title: z.string(),\n /** Video length in seconds (from CMS); null when not yet set */\n duration: z.number().int().nullable(),\n /** CMS 免費試看 flag; playback access is decided by user role (out of scope here) */\n })\n .openapi('CourseLessonMeta')\n\nexport const V1CourseInstructorSchema = z\n .object({\n id: z.string(),\n slug: z.string(),\n name: z.string(),\n title: z.string(),\n bio: z.string(),\n avatarUrl: z.string().nullable(),\n })\n .openapi('CourseInstructor')\n\nexport const V1CourseResourceSchema = z\n .object({\n id: z.string(),\n title: z.string(),\n description: z.string(),\n /** GCS file URL; empty when no PDF uploaded */\n downloadUrl: z.string(),\n })\n .openapi('CourseResource')\n\nexport const V1CourseFurtherReadingSchema = z\n .object({\n id: z.string(),\n title: z.string(),\n excerpt: z.string(),\n thumbnailUrl: z.string().nullable(),\n url: z.string(),\n })\n .openapi('CourseFurtherReading')\n\nexport const V1CourseStatusSchema = z.enum(['published', 'coming_soon'])\n\nexport const V1HeaderCourseBadgeSchema = z.enum(['new', 'wip'])\n\nexport const V1HeaderCourseItemSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n badge: V1HeaderCourseBadgeSchema.optional(),\n })\n .openapi('HeaderCourseItem')\n\nexport const V1CoursesListResponseSchema = z\n .object({\n courses: z.array(V1HeaderCourseItemSchema),\n })\n .openapi('CoursesListResponse')\n\nexport const V1CourseTagSchema = z.object({\n slug: z.string(),\n name: z.string(),\n})\n\nexport const V1ClassroomBySlugResponseSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n summary: z.string(),\n /** published: full payload; coming_soon: lessons/resources/furtherReading/previewVideoId stripped */\n status: V1CourseStatusSchema,\n tags: z.array(V1CourseTagSchema),\n /** Trial/preview stream only; null when unconfigured or course is coming_soon */\n previewVideoId: z.string().nullable(),\n lessons: z.array(V1CourseLessonSchema),\n instructors: z.array(V1CourseInstructorSchema),\n resources: z.array(V1CourseResourceSchema),\n furtherReading: z.array(V1CourseFurtherReadingSchema),\n })\n .openapi('ClassroomDetail')\n\nexport const V1CourseBySlugResponseSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n summary: z.string(),\n launchAt: z.iso.datetime().nullable(),\n description: JsonValueSchema.nullable(),\n /** published: full payload; coming_soon: lessons/resources/furtherReading/previewVideoId stripped */\n status: V1CourseStatusSchema,\n tags: z.array(V1CourseTagSchema),\n /** Trial/preview stream only; null when unconfigured or course is coming_soon */\n trialVideos: z.array(CloudflareStreamVideoSchema).nullable(),\n lessonsMeta: z.array(V1CourseLessonMetaSchema),\n instructors: z.array(V1CourseInstructorSchema),\n heroImage: PhotoSchema.nullable(),\n })\n .openapi('CourseDetail')\n\n// --- OpenAPI path registration ---\n\nconst internalServerErrorResponse = {\n 500: {\n description: 'Internal server error',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/courses',\n tags: ['Courses'],\n description: 'Header course list.',\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1CoursesListResponseSchema },\n },\n },\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/courses/{slug}/meta',\n tags: ['Courses'],\n description: 'OG metadata for a course page.',\n request: { params: V1CourseSlugPathParamsSchema },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1CourseBySlugMetaResponseSchema },\n },\n },\n 400: {\n description: 'Bad request',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 404: {\n description: 'Course not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/courses/{slug}',\n tags: ['Courses'],\n description:\n 'Full course detail for the classroom page. When status is coming_soon, lessons, resources, furtherReading, and previewVideoId are empty/null while title, description, tags, and instructors remain visible.',\n request: { params: V1CourseSlugPathParamsSchema },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1CourseBySlugResponseSchema },\n },\n },\n 400: {\n description: 'Bad request',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 404: {\n description: 'Course not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n"],"mappings":"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","ignoreList":[]}
@@ -8,6 +8,8 @@ export declare const V1MemberProfileSchema: z.ZodObject<{
8
8
  name: z.ZodString;
9
9
  twreporterUserId: z.ZodString;
10
10
  hasAccess: z.ZodBoolean;
11
+ role: z.ZodNullable<z.ZodString>;
12
+ expiredAt: z.ZodNullable<z.ZodISODateTime>;
11
13
  createdAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
12
14
  }, z.core.$strip>;
13
15
  export declare const V1MemberProfileResponseSchema: z.ZodObject<{
@@ -16,6 +18,8 @@ export declare const V1MemberProfileResponseSchema: z.ZodObject<{
16
18
  name: z.ZodString;
17
19
  twreporterUserId: z.ZodString;
18
20
  hasAccess: z.ZodBoolean;
21
+ role: z.ZodNullable<z.ZodString>;
22
+ expiredAt: z.ZodNullable<z.ZodISODateTime>;
19
23
  createdAt: z.ZodOptional<z.ZodNullable<z.ZodISODateTime>>;
20
24
  }, z.core.$strip>;
21
25
  export declare const V1AccessTokenResponseSchema: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../../src/schemas/member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,qBAAqB;;iBAYP,CAAA;AAE3B,eAAO,MAAM,qBAAqB;;;;;;;iBASP,CAAA;AAE3B,eAAO,MAAM,6BAA6B;;;;;;;iBAAwB,CAAA;AAElE,eAAO,MAAM,2BAA2B;;;;iBAMP,CAAA;AAEjC,eAAO,MAAM,6BAA6B;;iBAIP,CAAA;AAEnC,eAAO,MAAM,gCAAgC;;;;EAI3C,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;iBAKP,CAAA"}
1
+ {"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../../src/schemas/member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,qBAAqB;;iBAYP,CAAA;AAE3B,eAAO,MAAM,qBAAqB;;;;;;;;;iBAWP,CAAA;AAE3B,eAAO,MAAM,6BAA6B;;;;;;;;;iBAAwB,CAAA;AAElE,eAAO,MAAM,2BAA2B;;;;iBAMP,CAAA;AAEjC,eAAO,MAAM,6BAA6B;;iBAIP,CAAA;AAEnC,eAAO,MAAM,gCAAgC;;;;EAI3C,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;iBAKP,CAAA"}
@@ -16,6 +16,8 @@ export const V1MemberProfileSchema = z.object({
16
16
  name: z.string(),
17
17
  twreporterUserId: z.string(),
18
18
  hasAccess: z.boolean(),
19
+ role: z.string().nullable(),
20
+ expiredAt: z.iso.datetime().nullable(),
19
21
  createdAt: z.iso.datetime().nullable().optional()
20
22
  }).openapi('MemberProfile');
21
23
  export const V1MemberProfileResponseSchema = V1MemberProfileSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"member.js","names":["z","RestErrorBodySchema","registry","V1MemberMeQuerySchema","object","refreshAccess","preprocess","v","undefined","Array","isArray","boolean","optional","openapi","V1MemberProfileSchema","id","string","email","name","twreporterUserId","hasAccess","createdAt","iso","datetime","nullable","V1MemberProfileResponseSchema","V1AccessTokenResponseSchema","accessToken","expiresAt","number","V1RevokeMemberCacheBodySchema","V1RevokeMemberCacheOutcomeSchema","enum","V1RevokeMemberCacheResponseSchema","ok","literal","outcome","unauthorizedResponse","description","content","schema","internalServerErrorResponse","registerPath","method","path","tags","responses","request","query","body"],"sources":["../../src/schemas/member.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { RestErrorBodySchema } from '../rest.js'\nimport { registry } from './registry.js'\n\nexport const V1MemberMeQuerySchema = z\n .object({\n refreshAccess: z\n .preprocess((v) => {\n if (v === undefined) return undefined\n if (Array.isArray(v)) return v[0]\n if (v === true || v === 'true' || v === '1') return true\n if (v === false || v === 'false' || v === '0') return false\n return v\n }, z.boolean())\n .optional(),\n })\n .openapi('MemberMeQuery')\n\nexport const V1MemberProfileSchema = z\n .object({\n id: z.string(),\n email: z.string(),\n name: z.string(),\n twreporterUserId: z.string(),\n hasAccess: z.boolean(),\n createdAt: z.iso.datetime().nullable().optional(),\n })\n .openapi('MemberProfile')\n\nexport const V1MemberProfileResponseSchema = V1MemberProfileSchema\n\nexport const V1AccessTokenResponseSchema = z\n .object({\n accessToken: z.string(),\n twreporterUserId: z.string(),\n expiresAt: z.number(),\n })\n .openapi('AccessTokenResponse')\n\nexport const V1RevokeMemberCacheBodySchema = z\n .object({\n email: z.email(),\n })\n .openapi('RevokeMemberCacheBody')\n\nexport const V1RevokeMemberCacheOutcomeSchema = z.enum([\n 'revoked',\n 'not_found',\n 'manual_grant',\n])\n\nexport const V1RevokeMemberCacheResponseSchema = z\n .object({\n ok: z.literal(true),\n outcome: V1RevokeMemberCacheOutcomeSchema,\n })\n .openapi('RevokeMemberCacheResponse')\n\n// --- OpenAPI path registration ---\n\nconst unauthorizedResponse = {\n 401: {\n description: 'Unauthorized — missing or invalid JWT',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nconst internalServerErrorResponse = {\n 500: {\n description: 'Internal server error',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nregistry.registerPath({\n method: 'post',\n path: '/auth/access-token',\n tags: ['Auth'],\n description:\n 'Exchange id_token cookie for a JWT access token. Creates the member on first login.',\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1AccessTokenResponseSchema },\n },\n },\n 400: {\n description: 'Bad request — missing id_token cookie',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 403: {\n description: 'Forbidden — missing, invalid, or disallowed Origin',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...unauthorizedResponse,\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/members/me',\n tags: ['Members'],\n description:\n 'Get the authenticated member profile. Set refreshAccess=true to bypass the MemberAccess cache and re-fetch roles from go-api.',\n request: {\n query: V1MemberMeQuerySchema,\n },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1MemberProfileResponseSchema },\n },\n },\n 404: {\n description: 'Member not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...unauthorizedResponse,\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'post',\n path: '/v1/admin/members/revoke-cache',\n tags: ['Admin'],\n description:\n 'Invalidate MemberAccess cache for a member by email (clear checkedAt). Requires a Google OIDC ID token from an allowlisted caller. Terminal outcomes (revoked, not_found, manual_grant) always return 200 so Pub/Sub push can acknowledge delivery.',\n request: {\n body: {\n content: {\n 'application/json': { schema: V1RevokeMemberCacheBodySchema },\n },\n },\n },\n responses: {\n 200: {\n description:\n 'Request processed. outcome is revoked, not_found, or manual_grant.',\n content: {\n 'application/json': { schema: V1RevokeMemberCacheResponseSchema },\n },\n },\n 400: {\n description: 'Invalid request body',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 401: {\n description: 'Unauthorized — missing or invalid GCP IAM token',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 403: {\n description: 'Forbidden — valid token but caller not allowlisted',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"member.js","names":["z","RestErrorBodySchema","registry","V1MemberMeQuerySchema","object","refreshAccess","preprocess","v","undefined","Array","isArray","boolean","optional","openapi","V1MemberProfileSchema","id","string","email","name","twreporterUserId","hasAccess","role","nullable","expiredAt","iso","datetime","createdAt","V1MemberProfileResponseSchema","V1AccessTokenResponseSchema","accessToken","expiresAt","number","V1RevokeMemberCacheBodySchema","V1RevokeMemberCacheOutcomeSchema","enum","V1RevokeMemberCacheResponseSchema","ok","literal","outcome","unauthorizedResponse","description","content","schema","internalServerErrorResponse","registerPath","method","path","tags","responses","request","query","body"],"sources":["../../src/schemas/member.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { RestErrorBodySchema } from '../rest.js'\nimport { registry } from './registry.js'\n\nexport const V1MemberMeQuerySchema = z\n .object({\n refreshAccess: z\n .preprocess((v) => {\n if (v === undefined) return undefined\n if (Array.isArray(v)) return v[0]\n if (v === true || v === 'true' || v === '1') return true\n if (v === false || v === 'false' || v === '0') return false\n return v\n }, z.boolean())\n .optional(),\n })\n .openapi('MemberMeQuery')\n\nexport const V1MemberProfileSchema = z\n .object({\n id: z.string(),\n email: z.string(),\n name: z.string(),\n twreporterUserId: z.string(),\n hasAccess: z.boolean(),\n role: z.string().nullable(),\n expiredAt: z.iso.datetime().nullable(),\n createdAt: z.iso.datetime().nullable().optional(),\n })\n .openapi('MemberProfile')\n\nexport const V1MemberProfileResponseSchema = V1MemberProfileSchema\n\nexport const V1AccessTokenResponseSchema = z\n .object({\n accessToken: z.string(),\n twreporterUserId: z.string(),\n expiresAt: z.number(),\n })\n .openapi('AccessTokenResponse')\n\nexport const V1RevokeMemberCacheBodySchema = z\n .object({\n email: z.email(),\n })\n .openapi('RevokeMemberCacheBody')\n\nexport const V1RevokeMemberCacheOutcomeSchema = z.enum([\n 'revoked',\n 'not_found',\n 'manual_grant',\n])\n\nexport const V1RevokeMemberCacheResponseSchema = z\n .object({\n ok: z.literal(true),\n outcome: V1RevokeMemberCacheOutcomeSchema,\n })\n .openapi('RevokeMemberCacheResponse')\n\n// --- OpenAPI path registration ---\n\nconst unauthorizedResponse = {\n 401: {\n description: 'Unauthorized — missing or invalid JWT',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nconst internalServerErrorResponse = {\n 500: {\n description: 'Internal server error',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nregistry.registerPath({\n method: 'post',\n path: '/auth/access-token',\n tags: ['Auth'],\n description:\n 'Exchange id_token cookie for a JWT access token. Creates the member on first login.',\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1AccessTokenResponseSchema },\n },\n },\n 400: {\n description: 'Bad request — missing id_token cookie',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 403: {\n description: 'Forbidden — missing, invalid, or disallowed Origin',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...unauthorizedResponse,\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/members/me',\n tags: ['Members'],\n description:\n 'Get the authenticated member profile. Set refreshAccess=true to bypass the MemberAccess cache and re-fetch roles from go-api.',\n request: {\n query: V1MemberMeQuerySchema,\n },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1MemberProfileResponseSchema },\n },\n },\n 404: {\n description: 'Member not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...unauthorizedResponse,\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'post',\n path: '/v1/admin/members/revoke-cache',\n tags: ['Admin'],\n description:\n 'Invalidate MemberAccess cache for a member by email (clear checkedAt). Requires a Google OIDC ID token from an allowlisted caller. Terminal outcomes (revoked, not_found, manual_grant) always return 200 so Pub/Sub push can acknowledge delivery.',\n request: {\n body: {\n content: {\n 'application/json': { schema: V1RevokeMemberCacheBodySchema },\n },\n },\n },\n responses: {\n 200: {\n description:\n 'Request processed. outcome is revoked, not_found, or manual_grant.',\n content: {\n 'application/json': { schema: V1RevokeMemberCacheResponseSchema },\n },\n },\n 400: {\n description: 'Invalid request body',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 401: {\n description: 'Unauthorized — missing or invalid GCP IAM token',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 403: {\n description: 'Forbidden — valid token but caller not allowlisted',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export declare const PhotoResizedSchema: z.ZodObject<{
3
+ tiny: z.ZodString;
4
+ small: z.ZodString;
5
+ medium: z.ZodString;
6
+ large: z.ZodString;
7
+ }, z.core.$strip>;
8
+ export type PhotoResized = z.infer<typeof PhotoResizedSchema>;
9
+ export declare const PhotoSchema: z.ZodObject<{
10
+ title: z.ZodString;
11
+ resized: z.ZodObject<{
12
+ tiny: z.ZodString;
13
+ small: z.ZodString;
14
+ medium: z.ZodString;
15
+ large: z.ZodString;
16
+ }, z.core.$strip>;
17
+ }, z.core.$strip>;
18
+ //# sourceMappingURL=photo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"photo.d.ts","sourceRoot":"","sources":["../../src/schemas/photo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,kBAAkB;;;;;iBAK7B,CAAA;AACF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D,eAAO,MAAM,WAAW;;;;;;;;iBAGtB,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ export const PhotoResizedSchema = z.object({
3
+ tiny: z.string().min(1),
4
+ small: z.string().min(1),
5
+ medium: z.string().min(1),
6
+ large: z.string().min(1)
7
+ });
8
+ export const PhotoSchema = z.object({
9
+ title: z.string(),
10
+ resized: PhotoResizedSchema
11
+ });
12
+ //# sourceMappingURL=photo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"photo.js","names":["z","PhotoResizedSchema","object","tiny","string","min","small","medium","large","PhotoSchema","title","resized"],"sources":["../../src/schemas/photo.ts"],"sourcesContent":["import { z } from 'zod'\n\nexport const PhotoResizedSchema = z.object({\n tiny: z.string().min(1),\n small: z.string().min(1),\n medium: z.string().min(1),\n large: z.string().min(1),\n})\nexport type PhotoResized = z.infer<typeof PhotoResizedSchema>\n\nexport const PhotoSchema = z.object({\n title: z.string(),\n resized: PhotoResizedSchema,\n})\n"],"mappings":"AAAA,SAASA,CAAC,QAAQ,KAAK;AAEvB,OAAO,MAAMC,kBAAkB,GAAGD,CAAC,CAACE,MAAM,CAAC;EACzCC,IAAI,EAAEH,CAAC,CAACI,MAAM,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC,CAAC;EACvBC,KAAK,EAAEN,CAAC,CAACI,MAAM,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC,CAAC;EACxBE,MAAM,EAAEP,CAAC,CAACI,MAAM,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC,CAAC;EACzBG,KAAK,EAAER,CAAC,CAACI,MAAM,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC;AAGF,OAAO,MAAMI,WAAW,GAAGT,CAAC,CAACE,MAAM,CAAC;EAClCQ,KAAK,EAAEV,CAAC,CAACI,MAAM,CAAC,CAAC;EACjBO,OAAO,EAAEV;AACX,CAAC,CAAC","ignoreList":[]}
@@ -2,12 +2,12 @@ import { z } from 'zod';
2
2
  export declare const V1TagSlugPathParamsSchema: z.ZodObject<{
3
3
  slug: z.ZodString;
4
4
  }, z.core.$strip>;
5
- export declare const PhotoResizedSchema: z.ZodObject<{
6
- small: z.ZodString;
7
- }, z.core.$strip>;
8
5
  export declare const CourseThumbnailSchema: z.ZodObject<{
9
6
  resized: z.ZodObject<{
7
+ tiny: z.ZodString;
10
8
  small: z.ZodString;
9
+ medium: z.ZodString;
10
+ large: z.ZodString;
11
11
  }, z.core.$strip>;
12
12
  }, z.core.$strip>;
13
13
  export declare const V1TagBySlugMetaResponseSchema: z.ZodObject<{
@@ -15,7 +15,10 @@ export declare const V1TagBySlugMetaResponseSchema: z.ZodObject<{
15
15
  ogDescription: z.ZodString;
16
16
  ogImage: z.ZodNullable<z.ZodObject<{
17
17
  resized: z.ZodObject<{
18
+ tiny: z.ZodString;
18
19
  small: z.ZodString;
20
+ medium: z.ZodString;
21
+ large: z.ZodString;
19
22
  }, z.core.$strip>;
20
23
  }, z.core.$strip>>;
21
24
  }, z.core.$strip>;
@@ -30,7 +33,10 @@ export declare const CourseCardSchema: z.ZodObject<{
30
33
  summary: z.ZodString;
31
34
  thumbnail: z.ZodNullable<z.ZodObject<{
32
35
  resized: z.ZodObject<{
36
+ tiny: z.ZodString;
33
37
  small: z.ZodString;
38
+ medium: z.ZodString;
39
+ large: z.ZodString;
34
40
  }, z.core.$strip>;
35
41
  }, z.core.$strip>>;
36
42
  }, z.core.$strip>;
@@ -44,7 +50,10 @@ export declare const V1TagBySlugCoursesResponseSchema: z.ZodObject<{
44
50
  summary: z.ZodString;
45
51
  thumbnail: z.ZodNullable<z.ZodObject<{
46
52
  resized: z.ZodObject<{
53
+ tiny: z.ZodString;
47
54
  small: z.ZodString;
55
+ medium: z.ZodString;
56
+ large: z.ZodString;
48
57
  }, z.core.$strip>;
49
58
  }, z.core.$strip>>;
50
59
  }, z.core.$strip>>;
@@ -1 +1 @@
1
- {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/schemas/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,eAAO,MAAM,yBAAyB;;iBAEpC,CAAA;AAEF,eAAO,MAAM,kBAAkB;;iBAIL,CAAA;AAE1B,eAAO,MAAM,qBAAqB;;;;iBAIL,CAAA;AAI7B,eAAO,MAAM,6BAA6B;;;;;;;;iBAIxC,CAAA;AAIF,eAAO,MAAM,6BAA6B;;;iBAGxC,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;iBAQL,CAAA;AAExB,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;iBAI3C,CAAA"}
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/schemas/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB,eAAO,MAAM,yBAAyB;;iBAEpC,CAAA;AAEF,eAAO,MAAM,qBAAqB;;;;;;;iBAIL,CAAA;AAI7B,eAAO,MAAM,6BAA6B;;;;;;;;;;;iBAIxC,CAAA;AAIF,eAAO,MAAM,6BAA6B;;;iBAGxC,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;iBAQL,CAAA;AAExB,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;iBAI3C,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { RestErrorBodySchema } from '../rest.js';
3
+ import { PhotoResizedSchema } from './photo.js';
3
4
  import { registry } from './registry.js';
4
5
 
5
6
  // --- Shared path params ---
@@ -7,9 +8,6 @@ import { registry } from './registry.js';
7
8
  export const V1TagSlugPathParamsSchema = z.object({
8
9
  slug: z.string().min(1).max(200)
9
10
  });
10
- export const PhotoResizedSchema = z.object({
11
- small: z.string().min(1)
12
- }).openapi('ResizedPhoto');
13
11
  export const CourseThumbnailSchema = z.object({
14
12
  resized: PhotoResizedSchema
15
13
  }).openapi('CourseThumbnail');
@@ -1 +1 @@
1
- {"version":3,"file":"tag.js","names":["z","RestErrorBodySchema","registry","V1TagSlugPathParamsSchema","object","slug","string","min","max","PhotoResizedSchema","small","openapi","CourseThumbnailSchema","resized","V1TagBySlugMetaResponseSchema","ogTitle","ogDescription","ogImage","nullable","V1TagBySlugCoursesQuerySchema","take","coerce","number","int","optional","default","skip","CourseCardSchema","title","subtitle","summary","thumbnail","V1TagBySlugCoursesResponseSchema","name","coursesCount","courses","array","internalServerErrorResponse","description","content","schema","registerPath","method","path","tags","request","params","responses","query"],"sources":["../../src/schemas/tag.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { RestErrorBodySchema } from '../rest.js'\nimport { registry } from './registry.js'\n\n// --- Shared path params ---\n\nexport const V1TagSlugPathParamsSchema = z.object({\n slug: z.string().min(1).max(200),\n})\n\nexport const PhotoResizedSchema = z\n .object({\n small: z.string().min(1),\n })\n .openapi('ResizedPhoto')\n\nexport const CourseThumbnailSchema = z\n .object({\n resized: PhotoResizedSchema,\n })\n .openapi('CourseThumbnail')\n\n// --- Tag meta response ---\n\nexport const V1TagBySlugMetaResponseSchema = z.object({\n ogTitle: z.string(),\n ogDescription: z.string(),\n ogImage: CourseThumbnailSchema.nullable(),\n})\n\n// --- Tag courses query & response ---\n\nexport const V1TagBySlugCoursesQuerySchema = z.object({\n take: z.coerce.number().int().min(1).max(50).optional().default(12),\n skip: z.coerce.number().int().min(0).max(5000).optional().default(0),\n})\n\nexport const CourseCardSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n summary: z.string(),\n thumbnail: CourseThumbnailSchema.nullable(),\n })\n .openapi('CourseCard')\n\nexport const V1TagBySlugCoursesResponseSchema = z.object({\n name: z.string(),\n coursesCount: z.number().int().min(0),\n courses: z.array(CourseCardSchema),\n})\n\n// --- OpenAPI path registration ---\n\nconst internalServerErrorResponse = {\n 500: {\n description: 'Internal server error',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/tags/{slug}/meta',\n tags: ['Tags'],\n description: 'OG metadata for a tag page.',\n request: { params: V1TagSlugPathParamsSchema },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1TagBySlugMetaResponseSchema },\n },\n },\n 404: {\n description: 'Tag not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/tags/{slug}/courses',\n tags: ['Tags'],\n description: 'Courses for a tag (with count).',\n request: {\n params: V1TagSlugPathParamsSchema,\n query: V1TagBySlugCoursesQuerySchema,\n },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1TagBySlugCoursesResponseSchema },\n },\n },\n 404: {\n description: 'Tag not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 400: {\n description: 'Bad request',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"tag.js","names":["z","RestErrorBodySchema","PhotoResizedSchema","registry","V1TagSlugPathParamsSchema","object","slug","string","min","max","CourseThumbnailSchema","resized","openapi","V1TagBySlugMetaResponseSchema","ogTitle","ogDescription","ogImage","nullable","V1TagBySlugCoursesQuerySchema","take","coerce","number","int","optional","default","skip","CourseCardSchema","title","subtitle","summary","thumbnail","V1TagBySlugCoursesResponseSchema","name","coursesCount","courses","array","internalServerErrorResponse","description","content","schema","registerPath","method","path","tags","request","params","responses","query"],"sources":["../../src/schemas/tag.ts"],"sourcesContent":["import { z } from 'zod'\n\nimport { RestErrorBodySchema } from '../rest.js'\nimport { PhotoResizedSchema } from './photo.js'\nimport { registry } from './registry.js'\n\n// --- Shared path params ---\n\nexport const V1TagSlugPathParamsSchema = z.object({\n slug: z.string().min(1).max(200),\n})\n\nexport const CourseThumbnailSchema = z\n .object({\n resized: PhotoResizedSchema,\n })\n .openapi('CourseThumbnail')\n\n// --- Tag meta response ---\n\nexport const V1TagBySlugMetaResponseSchema = z.object({\n ogTitle: z.string(),\n ogDescription: z.string(),\n ogImage: CourseThumbnailSchema.nullable(),\n})\n\n// --- Tag courses query & response ---\n\nexport const V1TagBySlugCoursesQuerySchema = z.object({\n take: z.coerce.number().int().min(1).max(50).optional().default(12),\n skip: z.coerce.number().int().min(0).max(5000).optional().default(0),\n})\n\nexport const CourseCardSchema = z\n .object({\n slug: z.string(),\n title: z.string(),\n subtitle: z.string(),\n summary: z.string(),\n thumbnail: CourseThumbnailSchema.nullable(),\n })\n .openapi('CourseCard')\n\nexport const V1TagBySlugCoursesResponseSchema = z.object({\n name: z.string(),\n coursesCount: z.number().int().min(0),\n courses: z.array(CourseCardSchema),\n})\n\n// --- OpenAPI path registration ---\n\nconst internalServerErrorResponse = {\n 500: {\n description: 'Internal server error',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n} as const\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/tags/{slug}/meta',\n tags: ['Tags'],\n description: 'OG metadata for a tag page.',\n request: { params: V1TagSlugPathParamsSchema },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1TagBySlugMetaResponseSchema },\n },\n },\n 404: {\n description: 'Tag not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n\nregistry.registerPath({\n method: 'get',\n path: '/v1/tags/{slug}/courses',\n tags: ['Tags'],\n description: 'Courses for a tag (with count).',\n request: {\n params: V1TagSlugPathParamsSchema,\n query: V1TagBySlugCoursesQuerySchema,\n },\n responses: {\n 200: {\n description: 'Success',\n content: {\n 'application/json': { schema: V1TagBySlugCoursesResponseSchema },\n },\n },\n 404: {\n description: 'Tag not found',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n 400: {\n description: 'Bad request',\n content: { 'application/json': { schema: RestErrorBodySchema } },\n },\n ...internalServerErrorResponse,\n },\n})\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twreporter-academy/api-types",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "files": [