@read-frog/api-contract 0.19.0 → 0.20.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.
- package/dist/index.d.ts +375 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/contracts/card-template.ts +16 -4
- package/src/contracts/mastery-goal.ts +22 -0
- package/src/index.ts +3 -0
- package/src/public-errors.ts +33 -0
- package/src/schemas/mastery-goal.ts +23 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@read-frog/api-contract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@orpc/contract": "^1.15.2",
|
|
28
|
-
"@read-frog/definitions": "0.
|
|
28
|
+
"@read-frog/definitions": "0.9.0",
|
|
29
29
|
"zod": "^4.6.5"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -42,10 +42,16 @@ export const cardTemplateContract = {
|
|
|
42
42
|
path: "/card-templates",
|
|
43
43
|
summary: "Create card template",
|
|
44
44
|
description:
|
|
45
|
-
|
|
45
|
+
'Create a template in an owned notebase; it generates a card for every existing note. Each face (front, back) is either { columns: [column IDs], style }, those columns in a built-in style that stays editable in the website\'s simple mode, or { layout: "<HTML + Liquid>" } for a custom design that references a column as {{ ["<column id>"] }}. Prefer columns faces. Get column IDs from the notebase schema.',
|
|
46
46
|
tags: ["Card Templates"],
|
|
47
47
|
})
|
|
48
|
-
.errors(
|
|
48
|
+
.errors(
|
|
49
|
+
pickPublicErrorMap(
|
|
50
|
+
"NOTEBASE_NOT_FOUND",
|
|
51
|
+
"CARD_TEMPLATE_INVALID_NOTEBASE_COLUMNS",
|
|
52
|
+
"CARD_TEMPLATE_INVALID_LAYOUT",
|
|
53
|
+
),
|
|
54
|
+
)
|
|
49
55
|
.errors(pickPublicErrorMap("RESOURCE_ALREADY_EXISTS"))
|
|
50
56
|
.input(CardTemplateCreateInputSchema)
|
|
51
57
|
.output(CardTemplateCreateOutputSchema),
|
|
@@ -55,10 +61,16 @@ export const cardTemplateContract = {
|
|
|
55
61
|
path: "/card-templates/{id}",
|
|
56
62
|
summary: "Update card template",
|
|
57
63
|
description:
|
|
58
|
-
"Change an owned template name or
|
|
64
|
+
"Change an owned template name or faces (see creating a template for the face shapes). Rendered cards reflect the saved template. expectedUpdatedAt guards against editing stale data.",
|
|
59
65
|
tags: ["Card Templates"],
|
|
60
66
|
})
|
|
61
|
-
.errors(
|
|
67
|
+
.errors(
|
|
68
|
+
pickPublicErrorMap(
|
|
69
|
+
"CARD_TEMPLATE_NOT_FOUND",
|
|
70
|
+
"CARD_TEMPLATE_INVALID_NOTEBASE_COLUMNS",
|
|
71
|
+
"CARD_TEMPLATE_INVALID_LAYOUT",
|
|
72
|
+
),
|
|
73
|
+
)
|
|
62
74
|
.errors(pickPublicErrorMap("RESOURCE_UPDATE_CONFLICT"))
|
|
63
75
|
.input(CardTemplateUpdateInputSchema)
|
|
64
76
|
.output(CardTemplateUpdateOutputSchema),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { masteryGoalOutputSchema, masteryGoalUpdateInputSchema } from "#/schemas/mastery-goal";
|
|
3
|
+
|
|
4
|
+
export const masteryGoalContract = {
|
|
5
|
+
get: oc
|
|
6
|
+
.route({
|
|
7
|
+
method: "GET",
|
|
8
|
+
path: "/mastery-goal",
|
|
9
|
+
summary: "Get the authenticated user's mastered-cards goal",
|
|
10
|
+
tags: ["Goals"],
|
|
11
|
+
})
|
|
12
|
+
.output(masteryGoalOutputSchema),
|
|
13
|
+
update: oc
|
|
14
|
+
.route({
|
|
15
|
+
method: "PUT",
|
|
16
|
+
path: "/mastery-goal",
|
|
17
|
+
summary: "Set or clear the authenticated user's mastered-cards goal",
|
|
18
|
+
tags: ["Goals"],
|
|
19
|
+
})
|
|
20
|
+
.input(masteryGoalUpdateInputSchema)
|
|
21
|
+
.output(masteryGoalOutputSchema),
|
|
22
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { cardContract } from "./contracts/card";
|
|
|
5
5
|
import { cardTemplateContract } from "./contracts/card-template";
|
|
6
6
|
import { ebookContract } from "./contracts/ebook";
|
|
7
7
|
import { hostedAiContract } from "./contracts/hosted-ai";
|
|
8
|
+
import { masteryGoalContract } from "./contracts/mastery-goal";
|
|
8
9
|
import { mcpConnectionContract } from "./contracts/mcp-connection";
|
|
9
10
|
import { notebaseContract } from "./contracts/notebase";
|
|
10
11
|
import { notebaseColumnContract } from "./contracts/notebase-column";
|
|
@@ -21,6 +22,7 @@ export const contract = {
|
|
|
21
22
|
cardTemplate: cardTemplateContract,
|
|
22
23
|
ebook: ebookContract,
|
|
23
24
|
hostedAi: hostedAiContract,
|
|
25
|
+
masteryGoal: masteryGoalContract,
|
|
24
26
|
mcpConnection: mcpConnectionContract,
|
|
25
27
|
notebase: notebaseContract,
|
|
26
28
|
notebaseColumn: notebaseColumnContract,
|
|
@@ -40,6 +42,7 @@ export * from "./schemas/billing";
|
|
|
40
42
|
export * from "./schemas/card";
|
|
41
43
|
export * from "./schemas/ebook";
|
|
42
44
|
export * from "./schemas/hosted-ai";
|
|
45
|
+
export * from "./schemas/mastery-goal";
|
|
43
46
|
export * from "./schemas/mcp-connection";
|
|
44
47
|
export * from "./schemas/notebase";
|
|
45
48
|
export * from "./schemas/notebase-column";
|
package/src/public-errors.ts
CHANGED
|
@@ -45,6 +45,33 @@ export const CardTemplateInvalidColumnsDataSchema = z
|
|
|
45
45
|
.strict();
|
|
46
46
|
export type CardTemplateInvalidColumnsData = z.infer<typeof CardTemplateInvalidColumnsDataSchema>;
|
|
47
47
|
|
|
48
|
+
export const CardTemplateInvalidLayoutDataSchema = z
|
|
49
|
+
.object({
|
|
50
|
+
errors: z.array(
|
|
51
|
+
z
|
|
52
|
+
.object({
|
|
53
|
+
side: z.enum(["front", "back"]),
|
|
54
|
+
message: z.string(),
|
|
55
|
+
// UTF-16 offsets into that face's layout, when the parser knows them.
|
|
56
|
+
from: z.number().int().min(0).optional(),
|
|
57
|
+
to: z.number().int().min(0).optional(),
|
|
58
|
+
})
|
|
59
|
+
.strict(),
|
|
60
|
+
),
|
|
61
|
+
})
|
|
62
|
+
.strict();
|
|
63
|
+
export type CardTemplateInvalidLayoutData = z.infer<typeof CardTemplateInvalidLayoutDataSchema>;
|
|
64
|
+
|
|
65
|
+
// The templates that use the column, which keep it from being deleted.
|
|
66
|
+
export const CardTemplateNotebaseColumnInUseDataSchema = z
|
|
67
|
+
.object({
|
|
68
|
+
templates: z.array(z.object({ id: z.uuid(), name: z.string() }).strict()),
|
|
69
|
+
})
|
|
70
|
+
.strict();
|
|
71
|
+
export type CardTemplateNotebaseColumnInUseData = z.infer<
|
|
72
|
+
typeof CardTemplateNotebaseColumnInUseDataSchema
|
|
73
|
+
>;
|
|
74
|
+
|
|
48
75
|
export const HostedAiTierRestrictedDataSchema = z.strictObject({
|
|
49
76
|
modelTier: HostedAiModelTierSchema,
|
|
50
77
|
});
|
|
@@ -148,7 +175,13 @@ export const PUBLIC_APP_ERROR_DEFS = {
|
|
|
148
175
|
message: "Card template references unknown notebase columns",
|
|
149
176
|
status: 422,
|
|
150
177
|
},
|
|
178
|
+
CARD_TEMPLATE_INVALID_LAYOUT: {
|
|
179
|
+
data: CardTemplateInvalidLayoutDataSchema,
|
|
180
|
+
message: "Card template layout does not parse",
|
|
181
|
+
status: 422,
|
|
182
|
+
},
|
|
151
183
|
CARD_TEMPLATE_NOTEBASE_COLUMN_IN_USE: {
|
|
184
|
+
data: CardTemplateNotebaseColumnInUseDataSchema,
|
|
152
185
|
message: "Notebase column is used by a card template",
|
|
153
186
|
status: 409,
|
|
154
187
|
},
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const MASTERY_GOAL_TARGET_MAX = 1_000_000;
|
|
4
|
+
|
|
5
|
+
/** How many mastered cards to aim for: the cards `stats.srsMemoryGrowth` counts. */
|
|
6
|
+
export const masteryGoalTargetSchema = z.number().int().min(1).max(MASTERY_GOAL_TARGET_MAX);
|
|
7
|
+
export type MasteryGoalTarget = z.infer<typeof masteryGoalTargetSchema>;
|
|
8
|
+
|
|
9
|
+
/** `null` clears the goal. */
|
|
10
|
+
export const masteryGoalUpdateInputSchema = z
|
|
11
|
+
.object({
|
|
12
|
+
target: masteryGoalTargetSchema.nullable(),
|
|
13
|
+
})
|
|
14
|
+
.strict();
|
|
15
|
+
export type MasteryGoalUpdateInput = z.infer<typeof masteryGoalUpdateInputSchema>;
|
|
16
|
+
|
|
17
|
+
/** The goal's target, or `null` while none is set. */
|
|
18
|
+
export const masteryGoalOutputSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
target: masteryGoalTargetSchema.nullable(),
|
|
21
|
+
})
|
|
22
|
+
.strict();
|
|
23
|
+
export type MasteryGoalOutput = z.infer<typeof masteryGoalOutputSchema>;
|