@contractspec/module.learning-journey 3.7.6 → 3.7.10
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/README.md +65 -188
- package/dist/browser/contracts/index.js +148 -148
- package/dist/browser/contracts/models.js +1 -1
- package/dist/browser/contracts/onboarding.js +5 -5
- package/dist/browser/contracts/operations.js +4 -4
- package/dist/browser/engines/index.js +173 -173
- package/dist/browser/engines/xp.js +18 -18
- package/dist/browser/events.js +1 -1
- package/dist/browser/i18n/catalogs/index.js +18 -18
- package/dist/browser/i18n/index.js +26 -26
- package/dist/browser/i18n/locale.js +2 -2
- package/dist/browser/i18n/messages.js +18 -18
- package/dist/browser/index.js +336 -335
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +148 -148
- package/dist/contracts/models.js +1 -1
- package/dist/contracts/onboarding.js +5 -5
- package/dist/contracts/operations.js +4 -4
- package/dist/engines/index.d.ts +1 -1
- package/dist/engines/index.js +173 -173
- package/dist/engines/xp.js +18 -18
- package/dist/events.js +1 -1
- package/dist/i18n/catalogs/index.d.ts +1 -1
- package/dist/i18n/catalogs/index.js +18 -18
- package/dist/i18n/index.d.ts +7 -7
- package/dist/i18n/index.js +26 -26
- package/dist/i18n/locale.d.ts +1 -1
- package/dist/i18n/locale.js +2 -2
- package/dist/i18n/messages.js +18 -18
- package/dist/index.d.ts +3 -3
- package/dist/index.js +336 -335
- package/dist/node/contracts/index.js +148 -148
- package/dist/node/contracts/models.js +1 -1
- package/dist/node/contracts/onboarding.js +5 -5
- package/dist/node/contracts/operations.js +4 -4
- package/dist/node/engines/index.js +173 -173
- package/dist/node/engines/xp.js +18 -18
- package/dist/node/events.js +1 -1
- package/dist/node/i18n/catalogs/index.js +18 -18
- package/dist/node/i18n/index.js +26 -26
- package/dist/node/i18n/locale.js +2 -2
- package/dist/node/i18n/messages.js +18 -18
- package/dist/node/index.js +336 -335
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,200 +1,77 @@
|
|
|
1
1
|
# @contractspec/module.learning-journey
|
|
2
2
|
|
|
3
|
-
Website: https://contractspec.io
|
|
3
|
+
Website: https://contractspec.io
|
|
4
4
|
|
|
5
|
+
**Comprehensive learning journey engine - onboarding, LMS, flashcards, gamification, and AI personalization.**
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
## What It Provides
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
- **Layer**: module.
|
|
10
|
+
- **Consumers**: bundles (library, contractspec-studio), apps (web-landing).
|
|
11
|
+
- `src/contracts/` contains contract specs, operations, entities, and registry exports.
|
|
12
|
+
- `src/docs/` contains docblocks and documentation-facing exports.
|
|
13
|
+
- `src/contracts/` contains contract specs, operations, entities, and registry exports.
|
|
14
|
+
- `src/docs/` contains docblocks and documentation-facing exports.
|
|
9
15
|
|
|
10
|
-
|
|
16
|
+
## Installation
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
- **Learning Management System (LMS)**: Courses, modules, lessons, certifications
|
|
14
|
-
- **Flashcards & Spaced Repetition (SRS)**: SM-2 algorithm for optimal retention
|
|
15
|
-
- **Quizzes & Assessments**: Multiple question types, skill tracking
|
|
16
|
-
- **Gamification**: XP, streaks, achievements, leaderboards (Duolingo-style)
|
|
17
|
-
- **AI-Powered Personalization**: Adaptive paths, recommendations, gap detection
|
|
18
|
+
`npm install @contractspec/module.learning-journey`
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
or
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- **Courses**: Structured learning content with prerequisites and difficulty levels
|
|
24
|
-
- **Modules**: Groups of related lessons within a course
|
|
25
|
-
- **Lessons**: Individual learning units (content, video, interactive, quiz)
|
|
26
|
-
- **Progress Tracking**: Track completion, time spent, scores
|
|
27
|
-
|
|
28
|
-
### Product Onboarding
|
|
29
|
-
|
|
30
|
-
- **Onboarding Tracks**: Product-specific onboarding journeys
|
|
31
|
-
- **Event-Driven Completion**: Steps auto-complete when product events fire
|
|
32
|
-
- **Example**: "Create your first project" completes on `ProjectCreated` event
|
|
33
|
-
|
|
34
|
-
### Flashcards & Spaced Repetition
|
|
35
|
-
|
|
36
|
-
- **Decks & Cards**: Organize flashcards by topic
|
|
37
|
-
- **SM-2 Algorithm**: Optimized review scheduling
|
|
38
|
-
- **Review Sessions**: Get cards due for review
|
|
39
|
-
- **Retention Metrics**: Track long-term retention
|
|
40
|
-
|
|
41
|
-
### Quizzes & Assessments
|
|
42
|
-
|
|
43
|
-
- **Question Types**: Multiple choice, true/false, fill-in-blank, matching
|
|
44
|
-
- **Timed Quizzes**: Optional time limits
|
|
45
|
-
- **Skill Assessment**: Map quiz performance to skills
|
|
46
|
-
|
|
47
|
-
### Gamification
|
|
48
|
-
|
|
49
|
-
- **Experience Points (XP)**: Earn XP for completing activities
|
|
50
|
-
- **Streaks**: Maintain daily learning streaks
|
|
51
|
-
- **Achievements**: Unlock achievements for milestones
|
|
52
|
-
- **Leaderboards**: Compete with others (daily/weekly/monthly)
|
|
53
|
-
- **Lives System**: Optional hearts/lives for quiz attempts
|
|
54
|
-
|
|
55
|
-
### AI Personalization
|
|
56
|
-
|
|
57
|
-
- **Learner Profiles**: Track learning style, preferences, goals
|
|
58
|
-
- **Skill Maps**: Map proficiency across skills
|
|
59
|
-
- **Adaptive Paths**: Generate personalized learning sequences
|
|
60
|
-
- **Recommendations**: AI-powered content suggestions
|
|
61
|
-
- **Gap Detection**: Identify and address learning gaps
|
|
62
|
-
|
|
63
|
-
## Entities
|
|
64
|
-
|
|
65
|
-
### Course Structure
|
|
66
|
-
- `Course`, `Module`, `Lesson`, `LessonContent`
|
|
67
|
-
|
|
68
|
-
### Learner & Progress
|
|
69
|
-
- `Learner`, `Enrollment`, `LessonProgress`, `ModuleCompletion`, `Certificate`
|
|
70
|
-
|
|
71
|
-
### Onboarding
|
|
72
|
-
- `OnboardingTrack`, `OnboardingStep`, `OnboardingProgress`
|
|
73
|
-
|
|
74
|
-
### Flashcards
|
|
75
|
-
- `Deck`, `Card`, `CardReview`, `CardSchedule`
|
|
76
|
-
|
|
77
|
-
### Quizzes
|
|
78
|
-
- `Quiz`, `Question`, `QuestionOption`, `QuizAttempt`, `SkillAssessment`
|
|
79
|
-
|
|
80
|
-
### Gamification
|
|
81
|
-
- `Achievement`, `LearnerAchievement`, `Streak`, `DailyGoal`, `LeaderboardEntry`, `Heart`
|
|
82
|
-
|
|
83
|
-
### AI
|
|
84
|
-
- `LearnerProfile`, `SkillMap`, `LearningPath`, `Recommendation`
|
|
85
|
-
|
|
86
|
-
## Engines
|
|
87
|
-
|
|
88
|
-
### Spaced Repetition Engine (SRS)
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
import { SRSEngine } from '@contractspec/module.learning-journey/engines/srs';
|
|
92
|
-
|
|
93
|
-
const engine = new SRSEngine();
|
|
94
|
-
const nextReview = engine.calculateNextReview({
|
|
95
|
-
rating: 'good', // again, hard, good, easy
|
|
96
|
-
currentInterval: 1,
|
|
97
|
-
easeFactor: 2.5,
|
|
98
|
-
repetitions: 3,
|
|
99
|
-
});
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### XP Engine
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { XPEngine } from '@contractspec/module.learning-journey/engines/xp';
|
|
106
|
-
|
|
107
|
-
const engine = new XPEngine();
|
|
108
|
-
const xp = engine.calculate({
|
|
109
|
-
activity: 'lesson_complete',
|
|
110
|
-
score: 95,
|
|
111
|
-
streakBonus: true,
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Streak Engine
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
import { StreakEngine } from '@contractspec/module.learning-journey/engines/streak';
|
|
119
|
-
|
|
120
|
-
const engine = new StreakEngine();
|
|
121
|
-
const streak = engine.update({
|
|
122
|
-
lastActivityAt: new Date('2024-01-14'),
|
|
123
|
-
currentStreak: 5,
|
|
124
|
-
});
|
|
125
|
-
```
|
|
22
|
+
`bun add @contractspec/module.learning-journey`
|
|
126
23
|
|
|
127
24
|
## Usage
|
|
128
25
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
// ... other modules
|
|
182
|
-
],
|
|
183
|
-
};
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
26
|
+
Import the root entrypoint from `@contractspec/module.learning-journey`, or choose a documented subpath when you only need one part of the package surface.
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
- `src/contracts/` contains contract specs, operations, entities, and registry exports.
|
|
31
|
+
- `src/docs/` contains docblocks and documentation-facing exports.
|
|
32
|
+
- `src/engines` is part of the package's public or composition surface.
|
|
33
|
+
- `src/entities/` contains domain entities and value objects.
|
|
34
|
+
- `src/events.ts` is package-level event definitions.
|
|
35
|
+
- `src/i18n` is part of the package's public or composition surface.
|
|
36
|
+
- `src/index.ts` is the root public barrel and package entrypoint.
|
|
37
|
+
|
|
38
|
+
## Public Entry Points
|
|
39
|
+
|
|
40
|
+
- Export `.` resolves through `./src/index.ts`.
|
|
41
|
+
- Export `./contracts` resolves through `./src/contracts/index.ts`.
|
|
42
|
+
- Export `./contracts/models` resolves through `./src/contracts/models.ts`.
|
|
43
|
+
- Export `./contracts/onboarding` resolves through `./src/contracts/onboarding.ts`.
|
|
44
|
+
- Export `./contracts/operations` resolves through `./src/contracts/operations.ts`.
|
|
45
|
+
- Export `./contracts/shared` resolves through `./src/contracts/shared.ts`.
|
|
46
|
+
- Export `./docs` resolves through `./src/docs/index.ts`.
|
|
47
|
+
- Export `./docs/learning-journey.docblock` resolves through `./src/docs/learning-journey.docblock.ts`.
|
|
48
|
+
- Export `./engines` resolves through `./src/engines/index.ts`.
|
|
49
|
+
- Export `./engines/srs` resolves through `./src/engines/srs.ts`.
|
|
50
|
+
- The package publishes 32 total export subpaths; keep docs aligned with `package.json`.
|
|
51
|
+
|
|
52
|
+
## Local Commands
|
|
53
|
+
|
|
54
|
+
- `bun run dev` — contractspec-bun-build dev
|
|
55
|
+
- `bun run build` — bun run prebuild && bun run build:bundle && bun run build:types
|
|
56
|
+
- `bun run test` — bun test
|
|
57
|
+
- `bun run lint` — bun lint:fix
|
|
58
|
+
- `bun run lint:check` — biome check .
|
|
59
|
+
- `bun run lint:fix` — biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .
|
|
60
|
+
- `bun run typecheck` — tsc --noEmit
|
|
61
|
+
- `bun run publish:pkg` — bun publish --tolerate-republish --ignore-scripts --verbose
|
|
62
|
+
- `bun run publish:pkg:canary` — bun publish:pkg --tag canary
|
|
63
|
+
- `bun run clean` — rimraf dist .turbo
|
|
64
|
+
- `bun run build:bundle` — contractspec-bun-build transpile
|
|
65
|
+
- `bun run build:types` — contractspec-bun-build types
|
|
66
|
+
- `bun run prebuild` — contractspec-bun-build prebuild
|
|
67
|
+
|
|
68
|
+
## Recent Updates
|
|
69
|
+
|
|
70
|
+
- Replace eslint+prettier by biomejs to optimize speed.
|
|
71
|
+
- Add full i18n support across all 10 packages (en/fr/es, 460 keys).
|
|
72
|
+
|
|
73
|
+
## Notes
|
|
74
|
+
|
|
75
|
+
- SRS/streak/XP engines are pure functions -- keep them side-effect-free.
|
|
76
|
+
- i18n catalogs must stay in sync across all supported locales (en, es, fr).
|
|
77
|
+
- Entity schemas are shared with the UI; breaking changes propagate to all learning surfaces.
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
// src/contracts/shared.ts
|
|
2
|
-
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
3
|
-
|
|
4
1
|
// src/contracts/models.ts
|
|
5
|
-
import {
|
|
2
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
6
3
|
var CourseModel = defineSchemaModel({
|
|
7
4
|
name: "Course",
|
|
8
5
|
description: "A learning course",
|
|
@@ -178,149 +175,12 @@ var SuccessOutput = defineSchemaModel({
|
|
|
178
175
|
}
|
|
179
176
|
});
|
|
180
177
|
|
|
181
|
-
// src/contracts/
|
|
182
|
-
|
|
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
|
-
});
|
|
178
|
+
// src/contracts/shared.ts
|
|
179
|
+
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
320
180
|
|
|
321
181
|
// src/contracts/onboarding.ts
|
|
322
|
-
import {
|
|
323
|
-
import {
|
|
182
|
+
import { defineCommand, defineQuery } from "@contractspec/lib.contracts-spec";
|
|
183
|
+
import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
|
|
324
184
|
var OnboardingStepConditionModel = defineSchemaModel2({
|
|
325
185
|
name: "OnboardingStepCondition",
|
|
326
186
|
description: "Structured completion condition for onboarding steps.",
|
|
@@ -475,7 +335,7 @@ var RecordOnboardingEventInput = defineSchemaModel2({
|
|
|
475
335
|
occurredAt: { type: ScalarTypeEnum2.DateTime(), isOptional: true }
|
|
476
336
|
}
|
|
477
337
|
});
|
|
478
|
-
var ListOnboardingTracksContract =
|
|
338
|
+
var ListOnboardingTracksContract = defineQuery({
|
|
479
339
|
meta: {
|
|
480
340
|
key: "learning.onboarding.listTracks",
|
|
481
341
|
version: "1.0.0",
|
|
@@ -494,7 +354,7 @@ var ListOnboardingTracksContract = defineQuery2({
|
|
|
494
354
|
auth: "user"
|
|
495
355
|
}
|
|
496
356
|
});
|
|
497
|
-
var GetOnboardingProgressContract =
|
|
357
|
+
var GetOnboardingProgressContract = defineQuery({
|
|
498
358
|
meta: {
|
|
499
359
|
key: "learning.onboarding.getProgress",
|
|
500
360
|
version: "1.0.0",
|
|
@@ -513,7 +373,7 @@ var GetOnboardingProgressContract = defineQuery2({
|
|
|
513
373
|
auth: "user"
|
|
514
374
|
}
|
|
515
375
|
});
|
|
516
|
-
var RecordOnboardingEventContract =
|
|
376
|
+
var RecordOnboardingEventContract = defineCommand({
|
|
517
377
|
meta: {
|
|
518
378
|
key: "learning.onboarding.recordEvent",
|
|
519
379
|
version: "1.0.0",
|
|
@@ -546,6 +406,146 @@ var RecordOnboardingEventContract = defineCommand2({
|
|
|
546
406
|
auth: "user"
|
|
547
407
|
}
|
|
548
408
|
});
|
|
409
|
+
|
|
410
|
+
// src/contracts/operations.ts
|
|
411
|
+
import { defineCommand as defineCommand2, defineQuery as defineQuery2 } from "@contractspec/lib.contracts-spec";
|
|
412
|
+
var EnrollInCourseContract = defineCommand2({
|
|
413
|
+
meta: {
|
|
414
|
+
key: "learning.enroll",
|
|
415
|
+
version: "1.0.0",
|
|
416
|
+
stability: "stable",
|
|
417
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
418
|
+
tags: ["learning", "enrollment"],
|
|
419
|
+
description: "Enroll in a course.",
|
|
420
|
+
goal: "Start learning a new course.",
|
|
421
|
+
context: "Called when a learner wants to start a course."
|
|
422
|
+
},
|
|
423
|
+
io: {
|
|
424
|
+
input: EnrollInCourseInput,
|
|
425
|
+
output: EnrollmentModel,
|
|
426
|
+
errors: {
|
|
427
|
+
COURSE_NOT_FOUND: {
|
|
428
|
+
description: "Course does not exist",
|
|
429
|
+
http: 404,
|
|
430
|
+
gqlCode: "COURSE_NOT_FOUND",
|
|
431
|
+
when: "Course ID is invalid"
|
|
432
|
+
},
|
|
433
|
+
ALREADY_ENROLLED: {
|
|
434
|
+
description: "Already enrolled in course",
|
|
435
|
+
http: 409,
|
|
436
|
+
gqlCode: "ALREADY_ENROLLED",
|
|
437
|
+
when: "Learner is already enrolled"
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
policy: {
|
|
442
|
+
auth: "user"
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
var CompleteLessonContract = defineCommand2({
|
|
446
|
+
meta: {
|
|
447
|
+
key: "learning.completeLesson",
|
|
448
|
+
version: "1.0.0",
|
|
449
|
+
stability: "stable",
|
|
450
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
451
|
+
tags: ["learning", "progress"],
|
|
452
|
+
description: "Mark a lesson as completed.",
|
|
453
|
+
goal: "Record lesson completion and earn XP.",
|
|
454
|
+
context: "Called when a learner finishes a lesson."
|
|
455
|
+
},
|
|
456
|
+
io: {
|
|
457
|
+
input: CompleteLessonInput,
|
|
458
|
+
output: SuccessOutput,
|
|
459
|
+
errors: {
|
|
460
|
+
LESSON_NOT_FOUND: {
|
|
461
|
+
description: "Lesson does not exist",
|
|
462
|
+
http: 404,
|
|
463
|
+
gqlCode: "LESSON_NOT_FOUND",
|
|
464
|
+
when: "Lesson ID is invalid"
|
|
465
|
+
},
|
|
466
|
+
NOT_ENROLLED: {
|
|
467
|
+
description: "Not enrolled in course",
|
|
468
|
+
http: 403,
|
|
469
|
+
gqlCode: "NOT_ENROLLED",
|
|
470
|
+
when: "Learner is not enrolled in the course"
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
policy: {
|
|
475
|
+
auth: "user"
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
var SubmitCardReviewContract = defineCommand2({
|
|
479
|
+
meta: {
|
|
480
|
+
key: "learning.submitCardReview",
|
|
481
|
+
version: "1.0.0",
|
|
482
|
+
stability: "stable",
|
|
483
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
484
|
+
tags: ["learning", "flashcards"],
|
|
485
|
+
description: "Submit a flashcard review.",
|
|
486
|
+
goal: "Record review and update SRS schedule.",
|
|
487
|
+
context: "Called when reviewing flashcards."
|
|
488
|
+
},
|
|
489
|
+
io: {
|
|
490
|
+
input: SubmitCardReviewInput,
|
|
491
|
+
output: SuccessOutput,
|
|
492
|
+
errors: {
|
|
493
|
+
CARD_NOT_FOUND: {
|
|
494
|
+
description: "Card does not exist",
|
|
495
|
+
http: 404,
|
|
496
|
+
gqlCode: "CARD_NOT_FOUND",
|
|
497
|
+
when: "Card ID is invalid"
|
|
498
|
+
},
|
|
499
|
+
INVALID_RATING: {
|
|
500
|
+
description: "Invalid rating",
|
|
501
|
+
http: 400,
|
|
502
|
+
gqlCode: "INVALID_RATING",
|
|
503
|
+
when: "Rating must be AGAIN, HARD, GOOD, or EASY"
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
policy: {
|
|
508
|
+
auth: "user"
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
var GetDueCardsContract = defineQuery2({
|
|
512
|
+
meta: {
|
|
513
|
+
key: "learning.getDueCards",
|
|
514
|
+
version: "1.0.0",
|
|
515
|
+
stability: "stable",
|
|
516
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
517
|
+
tags: ["learning", "flashcards"],
|
|
518
|
+
description: "Get flashcards due for review.",
|
|
519
|
+
goal: "Get the next batch of cards to review.",
|
|
520
|
+
context: "Called when starting a review session."
|
|
521
|
+
},
|
|
522
|
+
io: {
|
|
523
|
+
input: GetDueCardsInput,
|
|
524
|
+
output: GetDueCardsOutput
|
|
525
|
+
},
|
|
526
|
+
policy: {
|
|
527
|
+
auth: "user"
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
var GetLearnerDashboardContract = defineQuery2({
|
|
531
|
+
meta: {
|
|
532
|
+
key: "learning.getDashboard",
|
|
533
|
+
version: "1.0.0",
|
|
534
|
+
stability: "stable",
|
|
535
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
536
|
+
tags: ["learning", "dashboard"],
|
|
537
|
+
description: "Get learner dashboard data.",
|
|
538
|
+
goal: "Display learner progress and stats.",
|
|
539
|
+
context: "Called when viewing the learning dashboard."
|
|
540
|
+
},
|
|
541
|
+
io: {
|
|
542
|
+
input: GetLearnerDashboardInput,
|
|
543
|
+
output: LearnerDashboardModel
|
|
544
|
+
},
|
|
545
|
+
policy: {
|
|
546
|
+
auth: "user"
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
549
|
export {
|
|
550
550
|
SuccessOutput,
|
|
551
551
|
SubmitCardReviewInput,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/contracts/models.ts
|
|
2
|
-
import {
|
|
2
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
3
3
|
var CourseModel = defineSchemaModel({
|
|
4
4
|
name: "Course",
|
|
5
5
|
description: "A learning course",
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
// src/contracts/shared.ts
|
|
2
|
-
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
3
|
-
|
|
4
1
|
// src/contracts/models.ts
|
|
5
|
-
import {
|
|
2
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
6
3
|
var CourseModel = defineSchemaModel({
|
|
7
4
|
name: "Course",
|
|
8
5
|
description: "A learning course",
|
|
@@ -178,9 +175,12 @@ var SuccessOutput = defineSchemaModel({
|
|
|
178
175
|
}
|
|
179
176
|
});
|
|
180
177
|
|
|
178
|
+
// src/contracts/shared.ts
|
|
179
|
+
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
180
|
+
|
|
181
181
|
// src/contracts/onboarding.ts
|
|
182
|
-
import { ScalarTypeEnum as ScalarTypeEnum2, defineSchemaModel as defineSchemaModel2 } from "@contractspec/lib.schema";
|
|
183
182
|
import { defineCommand, defineQuery } from "@contractspec/lib.contracts-spec";
|
|
183
|
+
import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
|
|
184
184
|
var OnboardingStepConditionModel = defineSchemaModel2({
|
|
185
185
|
name: "OnboardingStepCondition",
|
|
186
186
|
description: "Structured completion condition for onboarding steps.",
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
// src/contracts/shared.ts
|
|
2
|
-
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
3
|
-
|
|
4
1
|
// src/contracts/models.ts
|
|
5
|
-
import {
|
|
2
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
6
3
|
var CourseModel = defineSchemaModel({
|
|
7
4
|
name: "Course",
|
|
8
5
|
description: "A learning course",
|
|
@@ -178,6 +175,9 @@ var SuccessOutput = defineSchemaModel({
|
|
|
178
175
|
}
|
|
179
176
|
});
|
|
180
177
|
|
|
178
|
+
// src/contracts/shared.ts
|
|
179
|
+
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
180
|
+
|
|
181
181
|
// src/contracts/operations.ts
|
|
182
182
|
import { defineCommand, defineQuery } from "@contractspec/lib.contracts-spec";
|
|
183
183
|
var EnrollInCourseContract = defineCommand({
|