@contractspec/module.learning-journey 1.57.0 → 1.58.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/browser/contracts/index.js +578 -0
- package/dist/browser/contracts/models.js +193 -0
- package/dist/browser/contracts/onboarding.js +417 -0
- package/dist/browser/contracts/operations.js +326 -0
- package/dist/browser/contracts/shared.js +5 -0
- package/dist/browser/docs/index.js +124 -0
- package/dist/browser/docs/learning-journey.docblock.js +124 -0
- package/dist/browser/engines/index.js +526 -0
- package/dist/browser/engines/srs.js +198 -0
- package/dist/browser/engines/streak.js +159 -0
- package/dist/browser/engines/xp.js +171 -0
- package/dist/browser/entities/ai.js +343 -0
- package/dist/browser/entities/course.js +276 -0
- package/dist/browser/entities/flashcard.js +222 -0
- package/dist/browser/entities/gamification.js +340 -0
- package/dist/browser/entities/index.js +2136 -0
- package/dist/browser/entities/learner.js +329 -0
- package/dist/browser/entities/onboarding.js +301 -0
- package/dist/browser/entities/quiz.js +304 -0
- package/dist/browser/events.js +423 -0
- package/dist/browser/index.js +3833 -0
- package/dist/browser/learning-journey.capability.js +40 -0
- package/dist/browser/learning-journey.feature.js +56 -0
- package/dist/browser/track-spec.js +0 -0
- package/dist/contracts/index.d.ts +5 -5
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +578 -5
- package/dist/contracts/models.d.ts +426 -431
- package/dist/contracts/models.d.ts.map +1 -1
- package/dist/contracts/models.js +178 -372
- package/dist/contracts/onboarding.d.ts +621 -627
- package/dist/contracts/onboarding.d.ts.map +1 -1
- package/dist/contracts/onboarding.js +404 -388
- package/dist/contracts/operations.d.ts +243 -249
- package/dist/contracts/operations.d.ts.map +1 -1
- package/dist/contracts/operations.js +324 -148
- package/dist/contracts/shared.d.ts +1 -4
- package/dist/contracts/shared.d.ts.map +1 -1
- package/dist/contracts/shared.js +6 -6
- package/dist/docs/index.d.ts +2 -1
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +125 -1
- package/dist/docs/learning-journey.docblock.d.ts +2 -1
- package/dist/docs/learning-journey.docblock.d.ts.map +1 -0
- package/dist/docs/learning-journey.docblock.js +47 -58
- package/dist/engines/index.d.ts +4 -4
- package/dist/engines/index.d.ts.map +1 -0
- package/dist/engines/index.js +526 -4
- package/dist/engines/srs.d.ts +89 -92
- package/dist/engines/srs.d.ts.map +1 -1
- package/dist/engines/srs.js +197 -217
- package/dist/engines/streak.d.ts +84 -87
- package/dist/engines/streak.d.ts.map +1 -1
- package/dist/engines/streak.js +158 -192
- package/dist/engines/xp.d.ts +80 -83
- package/dist/engines/xp.d.ts.map +1 -1
- package/dist/engines/xp.js +170 -211
- package/dist/entities/ai.d.ts +199 -204
- package/dist/entities/ai.d.ts.map +1 -1
- package/dist/entities/ai.js +336 -368
- package/dist/entities/course.d.ts +149 -154
- package/dist/entities/course.d.ts.map +1 -1
- package/dist/entities/course.js +267 -306
- package/dist/entities/flashcard.d.ts +144 -149
- package/dist/entities/flashcard.d.ts.map +1 -1
- package/dist/entities/flashcard.js +217 -243
- package/dist/entities/gamification.d.ts +197 -202
- package/dist/entities/gamification.d.ts.map +1 -1
- package/dist/entities/gamification.js +331 -382
- package/dist/entities/index.d.ts +613 -618
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/index.js +2135 -43
- package/dist/entities/learner.d.ts +191 -196
- package/dist/entities/learner.d.ts.map +1 -1
- package/dist/entities/learner.js +322 -357
- package/dist/entities/onboarding.d.ts +164 -169
- package/dist/entities/onboarding.d.ts.map +1 -1
- package/dist/entities/onboarding.js +296 -301
- package/dist/entities/quiz.d.ts +184 -189
- package/dist/entities/quiz.d.ts.map +1 -1
- package/dist/entities/quiz.js +296 -361
- package/dist/events.d.ts +608 -614
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +421 -687
- package/dist/index.d.ts +8 -20
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3834 -22
- package/dist/learning-journey.capability.d.ts +3 -8
- package/dist/learning-journey.capability.d.ts.map +1 -1
- package/dist/learning-journey.capability.js +41 -46
- package/dist/learning-journey.feature.d.ts +1 -6
- package/dist/learning-journey.feature.d.ts.map +1 -1
- package/dist/learning-journey.feature.js +55 -155
- package/dist/node/contracts/index.js +578 -0
- package/dist/node/contracts/models.js +193 -0
- package/dist/node/contracts/onboarding.js +417 -0
- package/dist/node/contracts/operations.js +326 -0
- package/dist/node/contracts/shared.js +5 -0
- package/dist/node/docs/index.js +124 -0
- package/dist/node/docs/learning-journey.docblock.js +124 -0
- package/dist/node/engines/index.js +526 -0
- package/dist/node/engines/srs.js +198 -0
- package/dist/node/engines/streak.js +159 -0
- package/dist/node/engines/xp.js +171 -0
- package/dist/node/entities/ai.js +343 -0
- package/dist/node/entities/course.js +276 -0
- package/dist/node/entities/flashcard.js +222 -0
- package/dist/node/entities/gamification.js +340 -0
- package/dist/node/entities/index.js +2136 -0
- package/dist/node/entities/learner.js +329 -0
- package/dist/node/entities/onboarding.js +301 -0
- package/dist/node/entities/quiz.js +304 -0
- package/dist/node/events.js +423 -0
- package/dist/node/index.js +3833 -0
- package/dist/node/learning-journey.capability.js +40 -0
- package/dist/node/learning-journey.feature.js +56 -0
- package/dist/node/track-spec.js +0 -0
- package/dist/track-spec.d.ts +115 -118
- package/dist/track-spec.d.ts.map +1 -1
- package/dist/track-spec.js +1 -0
- package/package.json +237 -60
- package/dist/contracts/models.js.map +0 -1
- package/dist/contracts/onboarding.js.map +0 -1
- package/dist/contracts/operations.js.map +0 -1
- package/dist/contracts/shared.js.map +0 -1
- package/dist/docs/learning-journey.docblock.js.map +0 -1
- package/dist/engines/srs.js.map +0 -1
- package/dist/engines/streak.js.map +0 -1
- package/dist/engines/xp.js.map +0 -1
- package/dist/entities/ai.js.map +0 -1
- package/dist/entities/course.js.map +0 -1
- package/dist/entities/flashcard.js.map +0 -1
- package/dist/entities/gamification.js.map +0 -1
- package/dist/entities/index.js.map +0 -1
- package/dist/entities/learner.js.map +0 -1
- package/dist/entities/onboarding.js.map +0 -1
- package/dist/entities/quiz.js.map +0 -1
- package/dist/events.js.map +0 -1
- package/dist/learning-journey.capability.js.map +0 -1
- package/dist/learning-journey.feature.js.map +0 -1
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
// src/contracts/shared.ts
|
|
2
|
+
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
3
|
+
|
|
4
|
+
// src/contracts/models.ts
|
|
5
|
+
import { ScalarTypeEnum, defineSchemaModel } from "@contractspec/lib.schema";
|
|
6
|
+
var CourseModel = defineSchemaModel({
|
|
7
|
+
name: "Course",
|
|
8
|
+
description: "A learning course",
|
|
9
|
+
fields: {
|
|
10
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
11
|
+
title: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
12
|
+
slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
13
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
14
|
+
difficulty: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
15
|
+
status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
16
|
+
estimatedDuration: {
|
|
17
|
+
type: ScalarTypeEnum.Int_unsecure(),
|
|
18
|
+
isOptional: true
|
|
19
|
+
},
|
|
20
|
+
thumbnailUrl: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
21
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
var LearnerModel = defineSchemaModel({
|
|
25
|
+
name: "Learner",
|
|
26
|
+
description: "A learner profile",
|
|
27
|
+
fields: {
|
|
28
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
29
|
+
userId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
30
|
+
displayName: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
31
|
+
level: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
32
|
+
totalXp: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
33
|
+
currentStreak: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
34
|
+
longestStreak: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
35
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
var EnrollmentModel = defineSchemaModel({
|
|
39
|
+
name: "Enrollment",
|
|
40
|
+
description: "A course enrollment",
|
|
41
|
+
fields: {
|
|
42
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
43
|
+
learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
44
|
+
courseId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
45
|
+
status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
46
|
+
progress: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
47
|
+
startedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
48
|
+
completedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
var ProgressModel = defineSchemaModel({
|
|
52
|
+
name: "LessonProgress",
|
|
53
|
+
description: "Lesson progress",
|
|
54
|
+
fields: {
|
|
55
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
56
|
+
learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
57
|
+
lessonId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
58
|
+
status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
59
|
+
progress: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
60
|
+
score: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
|
|
61
|
+
timeSpent: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
62
|
+
completedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
var DeckModel = defineSchemaModel({
|
|
66
|
+
name: "Deck",
|
|
67
|
+
description: "A flashcard deck",
|
|
68
|
+
fields: {
|
|
69
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
70
|
+
title: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
71
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
72
|
+
cardCount: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
73
|
+
isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
74
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
var CardModel = defineSchemaModel({
|
|
78
|
+
name: "Card",
|
|
79
|
+
description: "A flashcard",
|
|
80
|
+
fields: {
|
|
81
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
82
|
+
deckId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
83
|
+
front: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
84
|
+
back: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
85
|
+
hints: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
86
|
+
isDue: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
87
|
+
nextReviewAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var AchievementModel = defineSchemaModel({
|
|
91
|
+
name: "Achievement",
|
|
92
|
+
description: "An achievement",
|
|
93
|
+
fields: {
|
|
94
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
95
|
+
key: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
96
|
+
name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
97
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
98
|
+
icon: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
99
|
+
xpReward: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
100
|
+
unlockedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
var EnrollInCourseInput = defineSchemaModel({
|
|
104
|
+
name: "EnrollInCourseInput",
|
|
105
|
+
description: "Input for enrolling in a course",
|
|
106
|
+
fields: {
|
|
107
|
+
courseId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
var CompleteLessonInput = defineSchemaModel({
|
|
111
|
+
name: "CompleteLessonInput",
|
|
112
|
+
description: "Input for completing a lesson",
|
|
113
|
+
fields: {
|
|
114
|
+
lessonId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
115
|
+
score: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
|
|
116
|
+
timeSpent: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
var SubmitCardReviewInput = defineSchemaModel({
|
|
120
|
+
name: "SubmitCardReviewInput",
|
|
121
|
+
description: "Input for submitting a card review",
|
|
122
|
+
fields: {
|
|
123
|
+
cardId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
124
|
+
rating: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
125
|
+
responseTimeMs: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
var GetDueCardsInput = defineSchemaModel({
|
|
129
|
+
name: "GetDueCardsInput",
|
|
130
|
+
description: "Input for getting due cards",
|
|
131
|
+
fields: {
|
|
132
|
+
deckId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
133
|
+
limit: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
var GetDueCardsOutput = defineSchemaModel({
|
|
137
|
+
name: "GetDueCardsOutput",
|
|
138
|
+
description: "Output for getting due cards",
|
|
139
|
+
fields: {
|
|
140
|
+
cards: { type: CardModel, isArray: true, isOptional: false },
|
|
141
|
+
total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
var GetLearnerDashboardInput = defineSchemaModel({
|
|
145
|
+
name: "GetLearnerDashboardInput",
|
|
146
|
+
description: "Input for getting learner dashboard",
|
|
147
|
+
fields: {
|
|
148
|
+
learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
var LearnerDashboardModel = defineSchemaModel({
|
|
152
|
+
name: "LearnerDashboard",
|
|
153
|
+
description: "Learner dashboard data",
|
|
154
|
+
fields: {
|
|
155
|
+
learner: { type: LearnerModel, isOptional: false },
|
|
156
|
+
currentStreak: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
157
|
+
dailyXpGoal: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
158
|
+
dailyXpProgress: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
159
|
+
activeEnrollments: {
|
|
160
|
+
type: EnrollmentModel,
|
|
161
|
+
isArray: true,
|
|
162
|
+
isOptional: false
|
|
163
|
+
},
|
|
164
|
+
recentAchievements: {
|
|
165
|
+
type: AchievementModel,
|
|
166
|
+
isArray: true,
|
|
167
|
+
isOptional: false
|
|
168
|
+
},
|
|
169
|
+
dueCardCount: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
var SuccessOutput = defineSchemaModel({
|
|
173
|
+
name: "SuccessOutput",
|
|
174
|
+
description: "Generic success output",
|
|
175
|
+
fields: {
|
|
176
|
+
success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
177
|
+
xpEarned: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// src/contracts/operations.ts
|
|
182
|
+
import { defineCommand, defineQuery } from "@contractspec/lib.contracts";
|
|
183
|
+
var EnrollInCourseContract = defineCommand({
|
|
184
|
+
meta: {
|
|
185
|
+
key: "learning.enroll",
|
|
186
|
+
version: "1.0.0",
|
|
187
|
+
stability: "stable",
|
|
188
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
189
|
+
tags: ["learning", "enrollment"],
|
|
190
|
+
description: "Enroll in a course.",
|
|
191
|
+
goal: "Start learning a new course.",
|
|
192
|
+
context: "Called when a learner wants to start a course."
|
|
193
|
+
},
|
|
194
|
+
io: {
|
|
195
|
+
input: EnrollInCourseInput,
|
|
196
|
+
output: EnrollmentModel,
|
|
197
|
+
errors: {
|
|
198
|
+
COURSE_NOT_FOUND: {
|
|
199
|
+
description: "Course does not exist",
|
|
200
|
+
http: 404,
|
|
201
|
+
gqlCode: "COURSE_NOT_FOUND",
|
|
202
|
+
when: "Course ID is invalid"
|
|
203
|
+
},
|
|
204
|
+
ALREADY_ENROLLED: {
|
|
205
|
+
description: "Already enrolled in course",
|
|
206
|
+
http: 409,
|
|
207
|
+
gqlCode: "ALREADY_ENROLLED",
|
|
208
|
+
when: "Learner is already enrolled"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
policy: {
|
|
213
|
+
auth: "user"
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
var CompleteLessonContract = defineCommand({
|
|
217
|
+
meta: {
|
|
218
|
+
key: "learning.completeLesson",
|
|
219
|
+
version: "1.0.0",
|
|
220
|
+
stability: "stable",
|
|
221
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
222
|
+
tags: ["learning", "progress"],
|
|
223
|
+
description: "Mark a lesson as completed.",
|
|
224
|
+
goal: "Record lesson completion and earn XP.",
|
|
225
|
+
context: "Called when a learner finishes a lesson."
|
|
226
|
+
},
|
|
227
|
+
io: {
|
|
228
|
+
input: CompleteLessonInput,
|
|
229
|
+
output: SuccessOutput,
|
|
230
|
+
errors: {
|
|
231
|
+
LESSON_NOT_FOUND: {
|
|
232
|
+
description: "Lesson does not exist",
|
|
233
|
+
http: 404,
|
|
234
|
+
gqlCode: "LESSON_NOT_FOUND",
|
|
235
|
+
when: "Lesson ID is invalid"
|
|
236
|
+
},
|
|
237
|
+
NOT_ENROLLED: {
|
|
238
|
+
description: "Not enrolled in course",
|
|
239
|
+
http: 403,
|
|
240
|
+
gqlCode: "NOT_ENROLLED",
|
|
241
|
+
when: "Learner is not enrolled in the course"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
policy: {
|
|
246
|
+
auth: "user"
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
var SubmitCardReviewContract = defineCommand({
|
|
250
|
+
meta: {
|
|
251
|
+
key: "learning.submitCardReview",
|
|
252
|
+
version: "1.0.0",
|
|
253
|
+
stability: "stable",
|
|
254
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
255
|
+
tags: ["learning", "flashcards"],
|
|
256
|
+
description: "Submit a flashcard review.",
|
|
257
|
+
goal: "Record review and update SRS schedule.",
|
|
258
|
+
context: "Called when reviewing flashcards."
|
|
259
|
+
},
|
|
260
|
+
io: {
|
|
261
|
+
input: SubmitCardReviewInput,
|
|
262
|
+
output: SuccessOutput,
|
|
263
|
+
errors: {
|
|
264
|
+
CARD_NOT_FOUND: {
|
|
265
|
+
description: "Card does not exist",
|
|
266
|
+
http: 404,
|
|
267
|
+
gqlCode: "CARD_NOT_FOUND",
|
|
268
|
+
when: "Card ID is invalid"
|
|
269
|
+
},
|
|
270
|
+
INVALID_RATING: {
|
|
271
|
+
description: "Invalid rating",
|
|
272
|
+
http: 400,
|
|
273
|
+
gqlCode: "INVALID_RATING",
|
|
274
|
+
when: "Rating must be AGAIN, HARD, GOOD, or EASY"
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
policy: {
|
|
279
|
+
auth: "user"
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
var GetDueCardsContract = defineQuery({
|
|
283
|
+
meta: {
|
|
284
|
+
key: "learning.getDueCards",
|
|
285
|
+
version: "1.0.0",
|
|
286
|
+
stability: "stable",
|
|
287
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
288
|
+
tags: ["learning", "flashcards"],
|
|
289
|
+
description: "Get flashcards due for review.",
|
|
290
|
+
goal: "Get the next batch of cards to review.",
|
|
291
|
+
context: "Called when starting a review session."
|
|
292
|
+
},
|
|
293
|
+
io: {
|
|
294
|
+
input: GetDueCardsInput,
|
|
295
|
+
output: GetDueCardsOutput
|
|
296
|
+
},
|
|
297
|
+
policy: {
|
|
298
|
+
auth: "user"
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
var GetLearnerDashboardContract = defineQuery({
|
|
302
|
+
meta: {
|
|
303
|
+
key: "learning.getDashboard",
|
|
304
|
+
version: "1.0.0",
|
|
305
|
+
stability: "stable",
|
|
306
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
307
|
+
tags: ["learning", "dashboard"],
|
|
308
|
+
description: "Get learner dashboard data.",
|
|
309
|
+
goal: "Display learner progress and stats.",
|
|
310
|
+
context: "Called when viewing the learning dashboard."
|
|
311
|
+
},
|
|
312
|
+
io: {
|
|
313
|
+
input: GetLearnerDashboardInput,
|
|
314
|
+
output: LearnerDashboardModel
|
|
315
|
+
},
|
|
316
|
+
policy: {
|
|
317
|
+
auth: "user"
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// src/contracts/onboarding.ts
|
|
322
|
+
import { ScalarTypeEnum as ScalarTypeEnum2, defineSchemaModel as defineSchemaModel2 } from "@contractspec/lib.schema";
|
|
323
|
+
import { defineCommand as defineCommand2, defineQuery as defineQuery2 } from "@contractspec/lib.contracts";
|
|
324
|
+
var OnboardingStepConditionModel = defineSchemaModel2({
|
|
325
|
+
name: "OnboardingStepCondition",
|
|
326
|
+
description: "Structured completion condition for onboarding steps.",
|
|
327
|
+
fields: {
|
|
328
|
+
eventName: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
329
|
+
eventVersion: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
330
|
+
sourceModule: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
331
|
+
payloadFilter: { type: ScalarTypeEnum2.JSON(), isOptional: true }
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
var OnboardingStepModel = defineSchemaModel2({
|
|
335
|
+
name: "OnboardingStep",
|
|
336
|
+
description: "Declarative onboarding step definition.",
|
|
337
|
+
fields: {
|
|
338
|
+
id: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
339
|
+
trackId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
340
|
+
title: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
341
|
+
description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
342
|
+
instructions: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
343
|
+
helpUrl: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
344
|
+
order: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: false },
|
|
345
|
+
completionEvent: {
|
|
346
|
+
type: ScalarTypeEnum2.String_unsecure(),
|
|
347
|
+
isOptional: false
|
|
348
|
+
},
|
|
349
|
+
completionCondition: {
|
|
350
|
+
type: OnboardingStepConditionModel,
|
|
351
|
+
isOptional: true
|
|
352
|
+
},
|
|
353
|
+
xpReward: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: true },
|
|
354
|
+
isRequired: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
|
|
355
|
+
canSkip: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
|
|
356
|
+
actionUrl: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
357
|
+
actionLabel: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
358
|
+
metadata: { type: ScalarTypeEnum2.JSON(), isOptional: true }
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
var OnboardingTrackModel = defineSchemaModel2({
|
|
362
|
+
name: "OnboardingTrack",
|
|
363
|
+
description: "Onboarding track metadata and steps.",
|
|
364
|
+
fields: {
|
|
365
|
+
id: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
366
|
+
productId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
367
|
+
name: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
368
|
+
description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
369
|
+
targetUserSegment: {
|
|
370
|
+
type: ScalarTypeEnum2.String_unsecure(),
|
|
371
|
+
isOptional: true
|
|
372
|
+
},
|
|
373
|
+
targetRole: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
374
|
+
isActive: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
|
|
375
|
+
isRequired: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
|
|
376
|
+
canSkip: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
|
|
377
|
+
totalXp: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: true },
|
|
378
|
+
completionXpBonus: {
|
|
379
|
+
type: ScalarTypeEnum2.Int_unsecure(),
|
|
380
|
+
isOptional: true
|
|
381
|
+
},
|
|
382
|
+
completionBadgeKey: {
|
|
383
|
+
type: ScalarTypeEnum2.String_unsecure(),
|
|
384
|
+
isOptional: true
|
|
385
|
+
},
|
|
386
|
+
streakHoursWindow: {
|
|
387
|
+
type: ScalarTypeEnum2.Int_unsecure(),
|
|
388
|
+
isOptional: true
|
|
389
|
+
},
|
|
390
|
+
streakBonusXp: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: true },
|
|
391
|
+
metadata: { type: ScalarTypeEnum2.JSON(), isOptional: true },
|
|
392
|
+
steps: { type: OnboardingStepModel, isArray: true, isOptional: false }
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
var OnboardingStepProgressModel = defineSchemaModel2({
|
|
396
|
+
name: "OnboardingStepProgress",
|
|
397
|
+
description: "Progress for a specific onboarding step.",
|
|
398
|
+
fields: {
|
|
399
|
+
stepId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
400
|
+
status: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
401
|
+
xpEarned: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: true },
|
|
402
|
+
triggeringEvent: {
|
|
403
|
+
type: ScalarTypeEnum2.String_unsecure(),
|
|
404
|
+
isOptional: true
|
|
405
|
+
},
|
|
406
|
+
eventPayload: { type: ScalarTypeEnum2.JSON(), isOptional: true },
|
|
407
|
+
completedAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true }
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
var OnboardingProgressModel = defineSchemaModel2({
|
|
411
|
+
name: "OnboardingProgress",
|
|
412
|
+
description: "Aggregated progress for an onboarding track.",
|
|
413
|
+
fields: {
|
|
414
|
+
learnerId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
415
|
+
trackId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
416
|
+
progress: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: false },
|
|
417
|
+
isCompleted: { type: ScalarTypeEnum2.Boolean(), isOptional: false },
|
|
418
|
+
xpEarned: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: true },
|
|
419
|
+
startedAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
|
|
420
|
+
completedAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
|
|
421
|
+
lastActivityAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
|
|
422
|
+
steps: {
|
|
423
|
+
type: OnboardingStepProgressModel,
|
|
424
|
+
isArray: true,
|
|
425
|
+
isOptional: true
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
var ListOnboardingTracksInput = defineSchemaModel2({
|
|
430
|
+
name: "ListOnboardingTracksInput",
|
|
431
|
+
description: "Filters for listing onboarding tracks.",
|
|
432
|
+
fields: {
|
|
433
|
+
learnerId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
434
|
+
productId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
435
|
+
trackIds: {
|
|
436
|
+
type: ScalarTypeEnum2.String_unsecure(),
|
|
437
|
+
isArray: true,
|
|
438
|
+
isOptional: true
|
|
439
|
+
},
|
|
440
|
+
includeProgress: {
|
|
441
|
+
type: ScalarTypeEnum2.Boolean(),
|
|
442
|
+
isOptional: true
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
var ListOnboardingTracksOutput = defineSchemaModel2({
|
|
447
|
+
name: "ListOnboardingTracksOutput",
|
|
448
|
+
description: "Available onboarding tracks with optional progress.",
|
|
449
|
+
fields: {
|
|
450
|
+
tracks: { type: OnboardingTrackModel, isArray: true, isOptional: false },
|
|
451
|
+
progress: {
|
|
452
|
+
type: OnboardingProgressModel,
|
|
453
|
+
isArray: true,
|
|
454
|
+
isOptional: true
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
var GetOnboardingProgressInput = defineSchemaModel2({
|
|
459
|
+
name: "GetOnboardingProgressInput",
|
|
460
|
+
description: "Input for fetching onboarding progress for a track.",
|
|
461
|
+
fields: {
|
|
462
|
+
trackId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
463
|
+
learnerId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true }
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
var RecordOnboardingEventInput = defineSchemaModel2({
|
|
467
|
+
name: "RecordOnboardingEventInput",
|
|
468
|
+
description: "Record a domain event to advance onboarding progress via completion conditions.",
|
|
469
|
+
fields: {
|
|
470
|
+
learnerId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
471
|
+
trackId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
472
|
+
eventName: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
|
|
473
|
+
eventVersion: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
|
|
474
|
+
eventPayload: { type: ScalarTypeEnum2.JSON(), isOptional: true },
|
|
475
|
+
occurredAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true }
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
var ListOnboardingTracksContract = defineQuery2({
|
|
479
|
+
meta: {
|
|
480
|
+
key: "learning.onboarding.listTracks",
|
|
481
|
+
version: "1.0.0",
|
|
482
|
+
stability: "stable",
|
|
483
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
484
|
+
tags: ["learning", "onboarding", "journey"],
|
|
485
|
+
description: "List onboarding tracks available to a learner or product.",
|
|
486
|
+
goal: "Expose track catalog for UI/API surfaces.",
|
|
487
|
+
context: "Called when showing onboarding/learning journey catalog."
|
|
488
|
+
},
|
|
489
|
+
io: {
|
|
490
|
+
input: ListOnboardingTracksInput,
|
|
491
|
+
output: ListOnboardingTracksOutput
|
|
492
|
+
},
|
|
493
|
+
policy: {
|
|
494
|
+
auth: "user"
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
var GetOnboardingProgressContract = defineQuery2({
|
|
498
|
+
meta: {
|
|
499
|
+
key: "learning.onboarding.getProgress",
|
|
500
|
+
version: "1.0.0",
|
|
501
|
+
stability: "stable",
|
|
502
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
503
|
+
tags: ["learning", "onboarding", "journey"],
|
|
504
|
+
description: "Fetch onboarding progress for a specific track.",
|
|
505
|
+
goal: "Display learner progress and remaining steps.",
|
|
506
|
+
context: "Called when rendering a track detail or widget."
|
|
507
|
+
},
|
|
508
|
+
io: {
|
|
509
|
+
input: GetOnboardingProgressInput,
|
|
510
|
+
output: OnboardingProgressModel
|
|
511
|
+
},
|
|
512
|
+
policy: {
|
|
513
|
+
auth: "user"
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
var RecordOnboardingEventContract = defineCommand2({
|
|
517
|
+
meta: {
|
|
518
|
+
key: "learning.onboarding.recordEvent",
|
|
519
|
+
version: "1.0.0",
|
|
520
|
+
stability: "stable",
|
|
521
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
522
|
+
tags: ["learning", "onboarding", "events"],
|
|
523
|
+
description: "Record a domain event to evaluate onboarding step completion conditions.",
|
|
524
|
+
goal: "Advance onboarding automatically from product events.",
|
|
525
|
+
context: "Called by event bus handlers when relevant product events fire (e.g., deal.created)."
|
|
526
|
+
},
|
|
527
|
+
io: {
|
|
528
|
+
input: RecordOnboardingEventInput,
|
|
529
|
+
output: SuccessOutput,
|
|
530
|
+
errors: {
|
|
531
|
+
TRACK_NOT_FOUND: {
|
|
532
|
+
description: "Track not found for event routing",
|
|
533
|
+
http: 404,
|
|
534
|
+
gqlCode: "TRACK_NOT_FOUND",
|
|
535
|
+
when: "Track ID or routing context is invalid"
|
|
536
|
+
},
|
|
537
|
+
STEP_NOT_FOUND: {
|
|
538
|
+
description: "Step not found for completion condition",
|
|
539
|
+
http: 404,
|
|
540
|
+
gqlCode: "STEP_NOT_FOUND",
|
|
541
|
+
when: "No step matches the incoming event"
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
policy: {
|
|
546
|
+
auth: "user"
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
export {
|
|
550
|
+
SuccessOutput,
|
|
551
|
+
SubmitCardReviewInput,
|
|
552
|
+
SubmitCardReviewContract,
|
|
553
|
+
RecordOnboardingEventContract,
|
|
554
|
+
ProgressModel,
|
|
555
|
+
OnboardingTrackModel,
|
|
556
|
+
OnboardingStepProgressModel,
|
|
557
|
+
OnboardingStepModel,
|
|
558
|
+
OnboardingProgressModel,
|
|
559
|
+
ListOnboardingTracksContract,
|
|
560
|
+
LearnerModel,
|
|
561
|
+
LearnerDashboardModel,
|
|
562
|
+
LEARNING_JOURNEY_OWNERS,
|
|
563
|
+
GetOnboardingProgressContract,
|
|
564
|
+
GetLearnerDashboardInput,
|
|
565
|
+
GetLearnerDashboardContract,
|
|
566
|
+
GetDueCardsOutput,
|
|
567
|
+
GetDueCardsInput,
|
|
568
|
+
GetDueCardsContract,
|
|
569
|
+
EnrollmentModel,
|
|
570
|
+
EnrollInCourseInput,
|
|
571
|
+
EnrollInCourseContract,
|
|
572
|
+
DeckModel,
|
|
573
|
+
CourseModel,
|
|
574
|
+
CompleteLessonInput,
|
|
575
|
+
CompleteLessonContract,
|
|
576
|
+
CardModel,
|
|
577
|
+
AchievementModel
|
|
578
|
+
};
|