@read-frog/api-contract 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/index.d.ts +1186 -481
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +326 -97
  4. package/dist/index.js.map +1 -1
  5. package/package.json +15 -14
  6. package/src/contracts/beta-access.ts +3 -6
  7. package/src/contracts/billing.ts +5 -5
  8. package/src/contracts/card-template.ts +45 -39
  9. package/src/contracts/card.ts +22 -19
  10. package/src/contracts/ebook.ts +13 -11
  11. package/src/contracts/hosted-ai.ts +5 -5
  12. package/src/contracts/mcp-connection.ts +26 -0
  13. package/src/contracts/notebase-column.ts +40 -32
  14. package/src/contracts/notebase-row.ts +85 -45
  15. package/src/contracts/notebase.ts +60 -40
  16. package/src/contracts/shared.ts +21 -2
  17. package/src/contracts/srs.ts +96 -63
  18. package/src/contracts/stats.ts +9 -11
  19. package/src/contracts/user.ts +3 -3
  20. package/src/contracts/video-transcript.ts +22 -12
  21. package/src/index.ts +40 -33
  22. package/src/public-errors.ts +74 -51
  23. package/src/schemas/beta-access.ts +12 -10
  24. package/src/schemas/billing.ts +103 -59
  25. package/src/schemas/card.ts +66 -63
  26. package/src/schemas/ebook.ts +165 -129
  27. package/src/schemas/hosted-ai.ts +84 -74
  28. package/src/schemas/mcp-connection.ts +28 -0
  29. package/src/schemas/notebase-column.ts +50 -36
  30. package/src/schemas/notebase-row.ts +88 -57
  31. package/src/schemas/notebase-stats.ts +28 -20
  32. package/src/schemas/notebase-view.ts +59 -49
  33. package/src/schemas/notebase.ts +136 -96
  34. package/src/schemas/pagination.ts +9 -0
  35. package/src/schemas/resource-mutation.ts +6 -0
  36. package/src/schemas/srs-stats.ts +30 -22
  37. package/src/schemas/srs.ts +152 -106
  38. package/src/schemas/stats.ts +27 -21
  39. package/src/schemas/timezone.ts +19 -16
  40. package/src/schemas/user.ts +27 -19
  41. package/src/schemas/video-transcript.ts +33 -32
@@ -1,3 +1,4 @@
1
+ import { paginationShape } from "./pagination";
1
2
  import {
2
3
  activeScheduleStatusSchema,
3
4
  cardStateSchema,
@@ -7,82 +8,84 @@ import {
7
8
  schedulingParamsSchema,
8
9
  SRS_REVIEW_DURATION_MS_MAX,
9
10
  srsStepSchema,
10
- } from "@read-frog/definitions"
11
- import { z } from "zod"
12
- import { cardSchema } from "./card"
13
- import { timezoneSchema } from "./timezone"
11
+ } from "@read-frog/definitions";
12
+ import { z } from "zod";
13
+ import { cardSchema } from "./card";
14
+ import { timezoneSchema } from "./timezone";
14
15
 
15
- export {
16
- reviewRatingSchema,
17
- schedulingParamsSchema,
18
- SRS_REVIEW_DURATION_MS_MAX,
19
- }
20
- export { timezoneSchema } from "./timezone"
21
- export type { Timezone } from "./timezone"
22
- export type { ReviewRating, SchedulingParams } from "@read-frog/definitions"
16
+ export { reviewRatingSchema, schedulingParamsSchema, SRS_REVIEW_DURATION_MS_MAX };
17
+ export { timezoneSchema } from "./timezone";
18
+ export type { Timezone } from "./timezone";
19
+ export type { ReviewRating, SchedulingParams } from "@read-frog/definitions";
23
20
 
24
- export const stepSchema = srsStepSchema
25
- export type Step = z.infer<typeof stepSchema>
21
+ export const stepSchema = srsStepSchema;
22
+ export type Step = z.infer<typeof stepSchema>;
26
23
 
27
- export const SRS_REVIEW_CLIENT_ID_NAMESPACE = "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
28
- const srsReviewClientIdNamePrefix = "readfrog:srs-review"
29
- const nullLastReviewTimeSentinel = "null"
24
+ export const SRS_REVIEW_CLIENT_ID_NAMESPACE = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
25
+ const srsReviewClientIdNamePrefix = "readfrog:srs-review";
26
+ const nullLastReviewTimeSentinel = "null";
30
27
 
31
28
  export interface SrsReviewClientIdCard {
32
- id: string
33
- lastReviewTime: Date | string | null
29
+ id: string;
30
+ lastReviewTime: Date | string | null;
34
31
  }
35
32
 
36
33
  export async function createSrsReviewClientId(card: SrsReviewClientIdCard) {
37
34
  return uuidV5(
38
35
  `${srsReviewClientIdNamePrefix}:${card.id}:${formatLastReviewTime(card.lastReviewTime)}`,
39
36
  SRS_REVIEW_CLIENT_ID_NAMESPACE,
40
- )
37
+ );
41
38
  }
42
39
 
43
- export const srsReviewInputSchema = z.object({
44
- cardId: z.uuid(),
45
- id: z.uuid().optional(),
46
- rating: reviewRatingSchema,
47
- durationMs: z.number().int().min(0).max(SRS_REVIEW_DURATION_MS_MAX),
48
- timezone: timezoneSchema,
49
- }).strict()
50
- export type SrsReviewInput = z.infer<typeof srsReviewInputSchema>
51
-
52
- export const srsRollbackReviewInputSchema = z.object({
53
- cardId: z.uuid(),
54
- }).strict()
55
- export type SrsRollbackReviewInput = z.infer<typeof srsRollbackReviewInputSchema>
40
+ export const srsReviewInputSchema = z
41
+ .object({
42
+ cardId: z.uuid(),
43
+ id: z.uuid().optional(),
44
+ rating: reviewRatingSchema,
45
+ durationMs: z.number().int().min(0).max(SRS_REVIEW_DURATION_MS_MAX),
46
+ timezone: timezoneSchema,
47
+ })
48
+ .strict();
49
+ export type SrsReviewInput = z.infer<typeof srsReviewInputSchema>;
50
+
51
+ export const srsRollbackReviewInputSchema = z
52
+ .object({
53
+ expectedReviewId: z.uuid().optional(),
54
+ cardId: z.uuid(),
55
+ })
56
+ .strict();
57
+ export type SrsRollbackReviewInput = z.infer<typeof srsRollbackReviewInputSchema>;
56
58
 
57
59
  export const srsScheduleStatusStatsSchema = z.record(
58
60
  activeScheduleStatusSchema,
59
61
  z.number().int().min(0),
60
- )
61
- export type SrsScheduleStatusStats = z.infer<typeof srsScheduleStatusStatsSchema>
62
-
63
- export const srsScheduleStatusStatsInputSchema = z.object({
64
- notebaseIds: z.array(z.uuid()).optional(),
65
- timezone: timezoneSchema,
66
- }).strict()
67
- export type SrsScheduleStatusStatsInput = z.infer<typeof srsScheduleStatusStatsInputSchema>
68
-
69
- export const srsScheduleStatusStatsOutputSchema = z.record(
70
- z.uuid(),
71
- srsScheduleStatusStatsSchema,
72
- )
73
- export type SrsScheduleStatusStatsOutput = z.infer<typeof srsScheduleStatusStatsOutputSchema>
74
-
75
- export const srsManualCardStatusInputSchema = z.object({
76
- cardId: z.uuid(),
77
- enabled: z.boolean(),
78
- }).strict()
79
- export type SrsManualCardStatusInput = z.infer<typeof srsManualCardStatusInputSchema>
80
-
81
- export const srsSetCardBuriedInputSchema = srsManualCardStatusInputSchema
82
- export type SrsSetCardBuriedInput = SrsManualCardStatusInput
83
-
84
- export const srsSetCardSuspendedInputSchema = srsManualCardStatusInputSchema
85
- export type SrsSetCardSuspendedInput = SrsManualCardStatusInput
62
+ );
63
+ export type SrsScheduleStatusStats = z.infer<typeof srsScheduleStatusStatsSchema>;
64
+
65
+ export const srsScheduleStatusStatsInputSchema = z
66
+ .object({
67
+ notebaseIds: z.array(z.uuid()).optional(),
68
+ timezone: timezoneSchema,
69
+ })
70
+ .strict();
71
+ export type SrsScheduleStatusStatsInput = z.infer<typeof srsScheduleStatusStatsInputSchema>;
72
+
73
+ export const srsScheduleStatusStatsOutputSchema = z.record(z.uuid(), srsScheduleStatusStatsSchema);
74
+ export type SrsScheduleStatusStatsOutput = z.infer<typeof srsScheduleStatusStatsOutputSchema>;
75
+
76
+ export const srsManualCardStatusInputSchema = z
77
+ .object({
78
+ cardId: z.uuid(),
79
+ enabled: z.boolean(),
80
+ })
81
+ .strict();
82
+ export type SrsManualCardStatusInput = z.infer<typeof srsManualCardStatusInputSchema>;
83
+
84
+ export const srsSetCardBuriedInputSchema = srsManualCardStatusInputSchema;
85
+ export type SrsSetCardBuriedInput = SrsManualCardStatusInput;
86
+
87
+ export const srsSetCardSuspendedInputSchema = srsManualCardStatusInputSchema;
88
+ export type SrsSetCardSuspendedInput = SrsManualCardStatusInput;
86
89
 
87
90
  export const srsRevlogSchema = z.object({
88
91
  id: z.uuid(),
@@ -97,23 +100,30 @@ export const srsRevlogSchema = z.object({
97
100
  durationMs: z.number().int(),
98
101
  fsrsReviewLogSnapshot: fsrsReviewLogSnapshotSchema,
99
102
  createdAt: z.coerce.date(),
100
- })
101
- export type SrsRevlog = z.infer<typeof srsRevlogSchema>
103
+ });
104
+ export type SrsRevlog = z.infer<typeof srsRevlogSchema>;
102
105
 
103
106
  export const srsRevlogWithoutSnapshotSchema = srsRevlogSchema.omit({
104
107
  fsrsReviewLogSnapshot: true,
105
- })
106
- export type SrsRevlogWithoutSnapshot = z.infer<typeof srsRevlogWithoutSnapshotSchema>
107
-
108
- export const srsListCardRevlogsInputSchema = z.object({
109
- cardId: z.uuid(),
110
- }).strict()
111
- export type SrsListCardRevlogsInput = z.infer<typeof srsListCardRevlogsInputSchema>
112
-
113
- export const srsListCardRevlogsOutputSchema = z.object({
114
- items: z.array(srsRevlogWithoutSnapshotSchema),
115
- }).strict()
116
- export type SrsListCardRevlogsOutput = z.infer<typeof srsListCardRevlogsOutputSchema>
108
+ });
109
+ export type SrsRevlogWithoutSnapshot = z.infer<typeof srsRevlogWithoutSnapshotSchema>;
110
+
111
+ export const srsListCardRevlogsInputSchema = z
112
+ .object({
113
+ ...paginationShape,
114
+ notebaseId: z.uuid().optional(),
115
+ cardId: z.uuid().optional(),
116
+ })
117
+ .strict();
118
+ export type SrsListCardRevlogsInput = z.infer<typeof srsListCardRevlogsInputSchema>;
119
+
120
+ export const srsListCardRevlogsOutputSchema = z
121
+ .object({
122
+ items: z.array(srsRevlogWithoutSnapshotSchema),
123
+ hasMore: z.boolean(),
124
+ })
125
+ .strict();
126
+ export type SrsListCardRevlogsOutput = z.infer<typeof srsListCardRevlogsOutputSchema>;
117
127
 
118
128
  export const srsReviewOutputSchema = z.object({
119
129
  card: cardSchema,
@@ -121,71 +131,107 @@ export const srsReviewOutputSchema = z.object({
121
131
  txid: z.number(),
122
132
  // False when an idempotent replay returned an existing revlog instead of creating one.
123
133
  created: z.boolean(),
124
- })
125
- export type SrsReviewOutput = z.infer<typeof srsReviewOutputSchema>
134
+ });
135
+ export type SrsReviewOutput = z.infer<typeof srsReviewOutputSchema>;
126
136
 
127
137
  export const srsRollbackReviewOutputSchema = z.object({
128
138
  card: cardSchema,
129
139
  rolledBackRevlogId: z.uuid(),
130
140
  txid: z.number(),
131
- })
132
- export type SrsRollbackReviewOutput = z.infer<typeof srsRollbackReviewOutputSchema>
141
+ });
142
+ export type SrsRollbackReviewOutput = z.infer<typeof srsRollbackReviewOutputSchema>;
133
143
 
134
144
  export const srsTxidOutputSchema = z.object({
135
145
  txid: z.number(),
136
- })
137
- export type SrsTxidOutput = z.infer<typeof srsTxidOutputSchema>
138
-
139
- export const srsSetCardBuriedOutputSchema = srsTxidOutputSchema
140
- export type SrsSetCardBuriedOutput = SrsTxidOutput
141
-
142
- export const srsSetCardSuspendedOutputSchema = srsTxidOutputSchema
143
- export type SrsSetCardSuspendedOutput = SrsTxidOutput
146
+ });
147
+ export type SrsTxidOutput = z.infer<typeof srsTxidOutputSchema>;
148
+
149
+ export const srsSetCardBuriedOutputSchema = srsTxidOutputSchema;
150
+ export type SrsSetCardBuriedOutput = SrsTxidOutput;
151
+
152
+ export const srsSetCardSuspendedOutputSchema = srsTxidOutputSchema;
153
+ export type SrsSetCardSuspendedOutput = SrsTxidOutput;
154
+
155
+ export const srsListUnreadOptimizerResultsInputSchema = z.object({}).strict();
156
+
157
+ export const srsOptimizerUnreadResultSchema = z
158
+ .object({
159
+ runId: z.uuid(),
160
+ notebaseName: z.string().min(1),
161
+ revlogCount: z.number().int().positive(),
162
+ improvement: z.number().nonnegative().nullable(),
163
+ })
164
+ .strict();
165
+ export type SrsOptimizerUnreadResult = z.infer<typeof srsOptimizerUnreadResultSchema>;
166
+
167
+ export const srsListUnreadOptimizerResultsOutputSchema = z.array(srsOptimizerUnreadResultSchema);
168
+ export type SrsListUnreadOptimizerResultsOutput = z.infer<
169
+ typeof srsListUnreadOptimizerResultsOutputSchema
170
+ >;
171
+
172
+ export const srsAcknowledgeOptimizerResultsInputSchema = z
173
+ .object({
174
+ runIds: z.array(z.uuid()).min(1),
175
+ })
176
+ .strict();
177
+ export type SrsAcknowledgeOptimizerResultsInput = z.infer<
178
+ typeof srsAcknowledgeOptimizerResultsInputSchema
179
+ >;
180
+
181
+ export const srsAcknowledgeOptimizerResultsOutputSchema = z
182
+ .object({
183
+ acknowledgedCount: z.number().int().nonnegative(),
184
+ })
185
+ .strict();
186
+ export type SrsAcknowledgeOptimizerResultsOutput = z.infer<
187
+ typeof srsAcknowledgeOptimizerResultsOutputSchema
188
+ >;
144
189
 
145
190
  function formatLastReviewTime(lastReviewTime: Date | string | null) {
146
- return lastReviewTime ? new Date(lastReviewTime).toISOString() : nullLastReviewTimeSentinel
191
+ return lastReviewTime ? new Date(lastReviewTime).toISOString() : nullLastReviewTimeSentinel;
147
192
  }
148
193
 
149
194
  async function uuidV5(name: string, namespace: string) {
150
- const namespaceBytes = uuidToBytes(namespace)
151
- const nameBytes = new TextEncoder().encode(name)
152
- const input = new Uint8Array(namespaceBytes.length + nameBytes.length)
153
- input.set(namespaceBytes)
154
- input.set(nameBytes, namespaceBytes.length)
155
-
156
- const hash = new Uint8Array(await crypto.subtle.digest("SHA-1", input))
157
- const bytes = hash.slice(0, 16)
158
- const versionByte = bytes[6]
159
- const variantByte = bytes[8]
195
+ const namespaceBytes = uuidToBytes(namespace);
196
+ const nameBytes = new TextEncoder().encode(name);
197
+ const input = new Uint8Array(namespaceBytes.length + nameBytes.length);
198
+ input.set(namespaceBytes);
199
+ input.set(nameBytes, namespaceBytes.length);
200
+
201
+ const hash = new Uint8Array(await crypto.subtle.digest("SHA-1", input));
202
+ const bytes = hash.slice(0, 16);
203
+ const versionByte = bytes[6];
204
+ const variantByte = bytes[8];
160
205
  if (versionByte === undefined || variantByte === undefined) {
161
- throw new Error("SHA-1 digest was too short")
206
+ throw new Error("SHA-1 digest was too short");
162
207
  }
163
- bytes[6] = (versionByte & 0x0F) | 0x50
164
- bytes[8] = (variantByte & 0x3F) | 0x80
208
+ bytes[6] = (versionByte & 0x0f) | 0x50;
209
+ bytes[8] = (variantByte & 0x3f) | 0x80;
165
210
 
166
- return bytesToUuid(bytes)
211
+ return bytesToUuid(bytes);
167
212
  }
168
213
 
169
214
  function uuidToBytes(uuid: string) {
170
- const hex = uuid.replaceAll("-", "").toLowerCase()
215
+ const hex = uuid.replaceAll("-", "").toLowerCase();
171
216
  /* v8 ignore next 3 -- SRS_REVIEW_CLIENT_ID_NAMESPACE is a fixed valid UUID. */
172
217
  if (!/^[0-9a-f]{32}$/.test(hex)) {
173
- throw new Error("Invalid UUID namespace")
218
+ throw new Error("Invalid UUID namespace");
174
219
  }
175
220
 
176
221
  return new Uint8Array(
177
222
  Array.from({ length: 16 }, (_, index) =>
178
- Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16)),
179
- )
223
+ Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16),
224
+ ),
225
+ );
180
226
  }
181
227
 
182
228
  function bytesToUuid(bytes: Uint8Array) {
183
- const hex = Array.from(bytes, byte => byte.toString(16).padStart(2, "0"))
229
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
184
230
  return [
185
231
  hex.slice(0, 4).join(""),
186
232
  hex.slice(4, 6).join(""),
187
233
  hex.slice(6, 8).join(""),
188
234
  hex.slice(8, 10).join(""),
189
235
  hex.slice(10, 16).join(""),
190
- ].join("-")
236
+ ].join("-");
191
237
  }
@@ -1,25 +1,31 @@
1
- import { z } from "zod"
2
- import { notebaseActivityStatsOutputSchema } from "./notebase-stats"
3
- import { srsActivityStatsOutputSchema } from "./srs-stats"
4
- import { timezoneSchema } from "./timezone"
1
+ import { z } from "zod";
2
+ import { notebaseActivityStatsOutputSchema } from "./notebase-stats";
3
+ import { srsActivityStatsOutputSchema } from "./srs-stats";
4
+ import { timezoneSchema } from "./timezone";
5
5
 
6
- const statsNotebaseIdsSchema = z.array(z.uuid())
6
+ const statsNotebaseIdsSchema = z
7
+ .array(z.uuid())
7
8
  .min(1)
8
- .transform(ids => Array.from(new Set(ids)))
9
+ .transform((ids) => Array.from(new Set(ids)));
9
10
 
10
- export const statsInputSchema = z.object({
11
- notebaseIds: statsNotebaseIdsSchema.optional(),
12
- from: z.iso.date().optional(),
13
- to: z.iso.date(),
14
- timezone: timezoneSchema,
15
- }).strict().refine(input => !input.from || input.from <= input.to, {
16
- message: "from must be before or equal to to",
17
- path: ["from"],
18
- })
19
- export type StatsInput = z.infer<typeof statsInputSchema>
11
+ export const statsInputSchema = z
12
+ .object({
13
+ notebaseIds: statsNotebaseIdsSchema.optional(),
14
+ from: z.iso.date().optional(),
15
+ to: z.iso.date(),
16
+ timezone: timezoneSchema,
17
+ })
18
+ .strict()
19
+ .refine((input) => !input.from || input.from <= input.to, {
20
+ message: "from must be before or equal to to",
21
+ path: ["from"],
22
+ });
23
+ export type StatsInput = z.infer<typeof statsInputSchema>;
20
24
 
21
- export const activityStatsOutputSchema = z.object({
22
- srs: srsActivityStatsOutputSchema,
23
- notebase: notebaseActivityStatsOutputSchema,
24
- }).strict()
25
- export type ActivityStatsOutput = z.infer<typeof activityStatsOutputSchema>
25
+ export const activityStatsOutputSchema = z
26
+ .object({
27
+ srs: srsActivityStatsOutputSchema,
28
+ notebase: notebaseActivityStatsOutputSchema,
29
+ })
30
+ .strict();
31
+ export type ActivityStatsOutput = z.infer<typeof activityStatsOutputSchema>;
@@ -1,23 +1,26 @@
1
- import { z } from "zod"
1
+ import { z } from "zod";
2
2
 
3
3
  // @ref https://zenn.dev/herp_inc/articles/js-intl-date-time-format-performance
4
- const localeTimeZoneFormatter = new Map<string, Intl.DateTimeFormat>()
4
+ const localeTimeZoneFormatter = new Map<string, Intl.DateTimeFormat>();
5
5
  function createTimezoneFormatter(timezone: string): Intl.DateTimeFormat {
6
- let formatter = localeTimeZoneFormatter.get(timezone)
6
+ let formatter = localeTimeZoneFormatter.get(timezone);
7
7
  if (!formatter) {
8
- formatter = new Intl.DateTimeFormat("en-US", { timeZone: timezone })
9
- localeTimeZoneFormatter.set(timezone, formatter)
8
+ formatter = new Intl.DateTimeFormat("en-US", { timeZone: timezone });
9
+ localeTimeZoneFormatter.set(timezone, formatter);
10
10
  }
11
- return formatter
11
+ return formatter;
12
12
  }
13
13
 
14
- export const timezoneSchema = z.string().trim().min(1).refine((timezone) => {
15
- try {
16
- createTimezoneFormatter(timezone).format(new Date())
17
- return true
18
- }
19
- catch {
20
- return false
21
- }
22
- }, "Invalid timezone")
23
- export type Timezone = z.infer<typeof timezoneSchema>
14
+ export const timezoneSchema = z
15
+ .string()
16
+ .trim()
17
+ .min(1)
18
+ .refine((timezone) => {
19
+ try {
20
+ createTimezoneFormatter(timezone).format(new Date());
21
+ return true;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }, "Invalid timezone");
26
+ export type Timezone = z.infer<typeof timezoneSchema>;
@@ -1,23 +1,31 @@
1
- import { z } from "zod"
2
- import { timezoneSchema } from "./timezone"
1
+ import { z } from "zod";
2
+ import { timezoneSchema } from "./timezone";
3
3
 
4
- export const userEnsureTimezoneInputSchema = z.object({
5
- timezone: timezoneSchema,
6
- }).strict()
7
- export type UserEnsureTimezoneInput = z.infer<typeof userEnsureTimezoneInputSchema>
4
+ export const userEnsureTimezoneInputSchema = z
5
+ .object({
6
+ timezone: timezoneSchema,
7
+ })
8
+ .strict();
9
+ export type UserEnsureTimezoneInput = z.infer<typeof userEnsureTimezoneInputSchema>;
8
10
 
9
- export const userEnsureTimezoneOutputSchema = z.object({
10
- timezone: timezoneSchema,
11
- updated: z.boolean(),
12
- }).strict()
13
- export type UserEnsureTimezoneOutput = z.infer<typeof userEnsureTimezoneOutputSchema>
11
+ export const userEnsureTimezoneOutputSchema = z
12
+ .object({
13
+ timezone: timezoneSchema,
14
+ updated: z.boolean(),
15
+ })
16
+ .strict();
17
+ export type UserEnsureTimezoneOutput = z.infer<typeof userEnsureTimezoneOutputSchema>;
14
18
 
15
- export const userUpdateTimezoneInputSchema = z.object({
16
- timezone: timezoneSchema,
17
- }).strict()
18
- export type UserUpdateTimezoneInput = z.infer<typeof userUpdateTimezoneInputSchema>
19
+ export const userUpdateTimezoneInputSchema = z
20
+ .object({
21
+ timezone: timezoneSchema,
22
+ })
23
+ .strict();
24
+ export type UserUpdateTimezoneInput = z.infer<typeof userUpdateTimezoneInputSchema>;
19
25
 
20
- export const userUpdateTimezoneOutputSchema = z.object({
21
- timezone: timezoneSchema,
22
- }).strict()
23
- export type UserUpdateTimezoneOutput = z.infer<typeof userUpdateTimezoneOutputSchema>
26
+ export const userUpdateTimezoneOutputSchema = z
27
+ .object({
28
+ timezone: timezoneSchema,
29
+ })
30
+ .strict();
31
+ export type UserUpdateTimezoneOutput = z.infer<typeof userUpdateTimezoneOutputSchema>;
@@ -1,14 +1,9 @@
1
- import { getVideoIdFromUrl, transcriptSegmentSchema } from "@read-frog/definitions"
2
- import { z } from "zod"
3
- import { billingPlanSchema } from "./billing"
1
+ import { getVideoIdFromUrl, transcriptSegmentSchema } from "@read-frog/definitions";
2
+ import { z } from "zod";
3
+ import { billingPlanSchema } from "./billing";
4
4
 
5
- export const videoTranscriptStatusSchema = z.enum([
6
- "pending",
7
- "processing",
8
- "completed",
9
- "failed",
10
- ])
11
- export type VideoTranscriptStatus = z.infer<typeof videoTranscriptStatusSchema>
5
+ export const videoTranscriptStatusSchema = z.enum(["pending", "processing", "completed", "failed"]);
6
+ export type VideoTranscriptStatus = z.infer<typeof videoTranscriptStatusSchema>;
12
7
 
13
8
  // The transcript "job" resource: status + metadata, without the (heavy) segments payload.
14
9
  export const videoTranscriptResourceSchema = z.object({
@@ -23,32 +18,38 @@ export const videoTranscriptResourceSchema = z.object({
23
18
  error: z.string().nullable(),
24
19
  createdAt: z.date(),
25
20
  updatedAt: z.date(),
26
- })
27
- export type VideoTranscriptResource = z.infer<typeof videoTranscriptResourceSchema>
21
+ });
22
+ export type VideoTranscriptResource = z.infer<typeof videoTranscriptResourceSchema>;
28
23
 
29
24
  // The subtitles sub-resource: the segments + model-detected language, only available once completed.
30
25
  export const videoTranscriptSubtitlesSchema = z.object({
31
26
  id: z.string(),
32
27
  detectedLanguage: z.string().nullable(),
33
28
  segments: z.array(transcriptSegmentSchema),
34
- })
35
- export type VideoTranscriptSubtitles = z.infer<typeof videoTranscriptSubtitlesSchema>
29
+ });
30
+ export type VideoTranscriptSubtitles = z.infer<typeof videoTranscriptSubtitlesSchema>;
36
31
 
37
- export const videoTranscriptCreateInputSchema = z.object({
38
- url: z.url().refine(url => getVideoIdFromUrl(url) !== null, { message: "url must be a supported video URL" }),
39
- // The player's own duration, read from the media element. REQUIRED, and an
40
- // untrusted UX hint only: admission uses it to reject an over-quota request
41
- // instantly, but every reservation and charge is made against the
42
- // server-measured duration in the worker — lying here changes nothing about
43
- // what gets billed.
44
- durationSec: z.number().int().positive(),
45
- }).strict()
46
- export type VideoTranscriptCreateInput = z.infer<typeof videoTranscriptCreateInputSchema>
32
+ export const videoTranscriptCreateInputSchema = z
33
+ .object({
34
+ url: z.url().refine((url) => getVideoIdFromUrl(url) !== null, {
35
+ message: "url must be a supported video URL",
36
+ }),
37
+ // The player's own duration, read from the media element. REQUIRED, and an
38
+ // untrusted UX hint only: admission uses it to reject an over-quota request
39
+ // instantly, but every reservation and charge is made against the
40
+ // server-measured duration in the worker — lying here changes nothing about
41
+ // what gets billed.
42
+ durationSec: z.number().int().positive(),
43
+ })
44
+ .strict();
45
+ export type VideoTranscriptCreateInput = z.infer<typeof videoTranscriptCreateInputSchema>;
47
46
 
48
- export const videoTranscriptGetInputSchema = z.object({
49
- id: z.uuid(),
50
- }).strict()
51
- export type VideoTranscriptGetInput = z.infer<typeof videoTranscriptGetInputSchema>
47
+ export const videoTranscriptGetInputSchema = z
48
+ .object({
49
+ id: z.uuid(),
50
+ })
51
+ .strict();
52
+ export type VideoTranscriptGetInput = z.infer<typeof videoTranscriptGetInputSchema>;
52
53
 
53
54
  // One quota pool as shown to the user. `resetAt` is null for a one-time grant
54
55
  // (it never resets); `expiresAt` is null for a monthly pool (its end is the
@@ -62,8 +63,8 @@ export const videoTranscriptUsagePoolSchema = z.object({
62
63
  remainingMinutes: z.number().int(),
63
64
  resetAt: z.iso.datetime().nullable(),
64
65
  expiresAt: z.iso.datetime().nullable(),
65
- })
66
- export type VideoTranscriptUsagePool = z.infer<typeof videoTranscriptUsagePoolSchema>
66
+ });
67
+ export type VideoTranscriptUsagePool = z.infer<typeof videoTranscriptUsagePoolSchema>;
67
68
 
68
69
  // The caller's transcription quota usage. Totals aggregate across pools;
69
70
  // `remainingMinutes` nets out in-flight reservations (committed), while each
@@ -76,5 +77,5 @@ export const videoTranscriptUsageSchema = z.object({
76
77
  remainingMinutes: z.number().int(),
77
78
  plan: billingPlanSchema,
78
79
  pools: z.array(videoTranscriptUsagePoolSchema),
79
- })
80
- export type VideoTranscriptUsage = z.infer<typeof videoTranscriptUsageSchema>
80
+ });
81
+ export type VideoTranscriptUsage = z.infer<typeof videoTranscriptUsageSchema>;