@contractspec/module.learning-journey 3.7.16 → 3.7.18

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 (94) hide show
  1. package/dist/browser/contracts/index.js +1 -578
  2. package/dist/browser/contracts/models.js +1 -193
  3. package/dist/browser/contracts/onboarding.js +1 -417
  4. package/dist/browser/contracts/operations.js +1 -326
  5. package/dist/browser/contracts/shared.js +1 -5
  6. package/dist/browser/docs/index.js +7 -51
  7. package/dist/browser/docs/learning-journey.docblock.js +7 -51
  8. package/dist/browser/engines/index.js +1 -675
  9. package/dist/browser/engines/srs.js +1 -198
  10. package/dist/browser/engines/streak.js +1 -159
  11. package/dist/browser/engines/xp.js +1 -320
  12. package/dist/browser/entities/ai.js +1 -343
  13. package/dist/browser/entities/course.js +1 -276
  14. package/dist/browser/entities/flashcard.js +1 -222
  15. package/dist/browser/entities/gamification.js +1 -340
  16. package/dist/browser/entities/index.js +1 -2140
  17. package/dist/browser/entities/learner.js +1 -333
  18. package/dist/browser/entities/onboarding.js +1 -301
  19. package/dist/browser/entities/quiz.js +1 -304
  20. package/dist/browser/events.js +1 -423
  21. package/dist/browser/i18n/catalogs/en.js +1 -43
  22. package/dist/browser/i18n/catalogs/es.js +1 -43
  23. package/dist/browser/i18n/catalogs/fr.js +1 -43
  24. package/dist/browser/i18n/catalogs/index.js +1 -127
  25. package/dist/browser/i18n/index.js +1 -169
  26. package/dist/browser/i18n/keys.js +1 -16
  27. package/dist/browser/i18n/locale.js +1 -13
  28. package/dist/browser/i18n/messages.js +1 -139
  29. package/dist/browser/index.js +7 -3914
  30. package/dist/browser/learning-journey.capability.js +1 -43
  31. package/dist/browser/learning-journey.feature.js +1 -56
  32. package/dist/contracts/index.js +1 -578
  33. package/dist/contracts/models.js +1 -193
  34. package/dist/contracts/onboarding.js +1 -417
  35. package/dist/contracts/operations.js +1 -326
  36. package/dist/contracts/shared.js +1 -5
  37. package/dist/docs/index.js +7 -51
  38. package/dist/docs/learning-journey.docblock.js +7 -51
  39. package/dist/engines/index.js +1 -675
  40. package/dist/engines/srs.js +1 -198
  41. package/dist/engines/streak.js +1 -159
  42. package/dist/engines/xp.js +1 -320
  43. package/dist/entities/ai.js +1 -343
  44. package/dist/entities/course.js +1 -276
  45. package/dist/entities/flashcard.js +1 -222
  46. package/dist/entities/gamification.js +1 -340
  47. package/dist/entities/index.js +1 -2140
  48. package/dist/entities/learner.js +1 -333
  49. package/dist/entities/onboarding.js +1 -301
  50. package/dist/entities/quiz.js +1 -304
  51. package/dist/events.js +1 -423
  52. package/dist/i18n/catalogs/en.js +1 -43
  53. package/dist/i18n/catalogs/es.js +1 -43
  54. package/dist/i18n/catalogs/fr.js +1 -43
  55. package/dist/i18n/catalogs/index.js +1 -127
  56. package/dist/i18n/index.js +1 -169
  57. package/dist/i18n/keys.js +1 -16
  58. package/dist/i18n/locale.js +1 -13
  59. package/dist/i18n/messages.js +1 -139
  60. package/dist/index.js +7 -3914
  61. package/dist/learning-journey.capability.js +1 -43
  62. package/dist/learning-journey.feature.js +1 -56
  63. package/dist/node/contracts/index.js +1 -578
  64. package/dist/node/contracts/models.js +1 -193
  65. package/dist/node/contracts/onboarding.js +1 -417
  66. package/dist/node/contracts/operations.js +1 -326
  67. package/dist/node/contracts/shared.js +1 -5
  68. package/dist/node/docs/index.js +7 -51
  69. package/dist/node/docs/learning-journey.docblock.js +7 -51
  70. package/dist/node/engines/index.js +1 -675
  71. package/dist/node/engines/srs.js +1 -198
  72. package/dist/node/engines/streak.js +1 -159
  73. package/dist/node/engines/xp.js +1 -320
  74. package/dist/node/entities/ai.js +1 -343
  75. package/dist/node/entities/course.js +1 -276
  76. package/dist/node/entities/flashcard.js +1 -222
  77. package/dist/node/entities/gamification.js +1 -340
  78. package/dist/node/entities/index.js +1 -2140
  79. package/dist/node/entities/learner.js +1 -333
  80. package/dist/node/entities/onboarding.js +1 -301
  81. package/dist/node/entities/quiz.js +1 -304
  82. package/dist/node/events.js +1 -423
  83. package/dist/node/i18n/catalogs/en.js +1 -43
  84. package/dist/node/i18n/catalogs/es.js +1 -43
  85. package/dist/node/i18n/catalogs/fr.js +1 -43
  86. package/dist/node/i18n/catalogs/index.js +1 -127
  87. package/dist/node/i18n/index.js +1 -169
  88. package/dist/node/i18n/keys.js +1 -16
  89. package/dist/node/i18n/locale.js +1 -13
  90. package/dist/node/i18n/messages.js +1 -139
  91. package/dist/node/index.js +7 -3914
  92. package/dist/node/learning-journey.capability.js +1 -43
  93. package/dist/node/learning-journey.feature.js +1 -56
  94. package/package.json +5 -5
@@ -1,223 +1,2 @@
1
1
  // @bun
2
- // src/entities/flashcard.ts
3
- import {
4
- defineEntity,
5
- defineEntityEnum,
6
- field,
7
- index
8
- } from "@contractspec/lib.schema";
9
- var CardRatingEnum = defineEntityEnum({
10
- name: "CardRating",
11
- values: ["AGAIN", "HARD", "GOOD", "EASY"],
12
- schema: "lssm_learning",
13
- description: "Rating for a flashcard review."
14
- });
15
- var DeckEntity = defineEntity({
16
- name: "Deck",
17
- description: "A collection of flashcards.",
18
- schema: "lssm_learning",
19
- map: "deck",
20
- fields: {
21
- id: field.id({ description: "Unique deck identifier" }),
22
- ownerId: field.foreignKey({ description: "Deck owner (learner)" }),
23
- title: field.string({ description: "Deck title" }),
24
- description: field.string({
25
- isOptional: true,
26
- description: "Deck description"
27
- }),
28
- category: field.string({ isOptional: true, description: "Deck category" }),
29
- tags: field.json({ isOptional: true, description: "Tags for discovery" }),
30
- isPublic: field.boolean({
31
- default: false,
32
- description: "Whether deck is publicly visible"
33
- }),
34
- cardCount: field.int({ default: 0, description: "Number of cards" }),
35
- coverImageUrl: field.string({
36
- isOptional: true,
37
- description: "Cover image URL"
38
- }),
39
- orgId: field.string({
40
- isOptional: true,
41
- description: "Organization scope"
42
- }),
43
- newCardsPerDay: field.int({
44
- default: 20,
45
- description: "New cards to introduce per day"
46
- }),
47
- reviewsPerDay: field.int({
48
- default: 100,
49
- description: "Maximum reviews per day"
50
- }),
51
- metadata: field.json({
52
- isOptional: true,
53
- description: "Additional metadata"
54
- }),
55
- createdAt: field.createdAt(),
56
- updatedAt: field.updatedAt(),
57
- owner: field.belongsTo("Learner", ["ownerId"], ["id"], {
58
- onDelete: "Cascade"
59
- }),
60
- cards: field.hasMany("Card")
61
- },
62
- indexes: [
63
- index.on(["ownerId"]),
64
- index.on(["isPublic", "category"]),
65
- index.on(["orgId"])
66
- ]
67
- });
68
- var CardEntity = defineEntity({
69
- name: "Card",
70
- description: "An individual flashcard.",
71
- schema: "lssm_learning",
72
- map: "card",
73
- fields: {
74
- id: field.id({ description: "Unique card identifier" }),
75
- deckId: field.foreignKey({ description: "Parent deck" }),
76
- front: field.string({ description: "Front of card (question)" }),
77
- back: field.string({ description: "Back of card (answer)" }),
78
- hints: field.json({ isOptional: true, description: "Hints for the card" }),
79
- explanation: field.string({
80
- isOptional: true,
81
- description: "Detailed explanation"
82
- }),
83
- frontMediaUrl: field.string({
84
- isOptional: true,
85
- description: "Media for front"
86
- }),
87
- backMediaUrl: field.string({
88
- isOptional: true,
89
- description: "Media for back"
90
- }),
91
- audioUrl: field.string({
92
- isOptional: true,
93
- description: "Audio pronunciation"
94
- }),
95
- tags: field.json({ isOptional: true, description: "Card tags" }),
96
- difficulty: field.int({ default: 0, description: "Card difficulty (0-5)" }),
97
- order: field.int({ default: 0, description: "Card order in deck" }),
98
- isSuspended: field.boolean({
99
- default: false,
100
- description: "Whether card is suspended"
101
- }),
102
- metadata: field.json({
103
- isOptional: true,
104
- description: "Additional metadata"
105
- }),
106
- createdAt: field.createdAt(),
107
- updatedAt: field.updatedAt(),
108
- deck: field.belongsTo("Deck", ["deckId"], ["id"], { onDelete: "Cascade" }),
109
- reviews: field.hasMany("CardReview"),
110
- schedules: field.hasMany("CardSchedule")
111
- },
112
- indexes: [index.on(["deckId", "order"]), index.on(["isSuspended"])]
113
- });
114
- var CardReviewEntity = defineEntity({
115
- name: "CardReview",
116
- description: "A single review of a flashcard.",
117
- schema: "lssm_learning",
118
- map: "card_review",
119
- fields: {
120
- id: field.id({ description: "Unique review identifier" }),
121
- learnerId: field.foreignKey({ description: "Reviewer" }),
122
- cardId: field.foreignKey({ description: "Reviewed card" }),
123
- rating: field.enum("CardRating", { description: "Review rating" }),
124
- responseTimeMs: field.int({
125
- isOptional: true,
126
- description: "Time to respond in ms"
127
- }),
128
- intervalBefore: field.int({ description: "Interval before review (days)" }),
129
- easeFactorBefore: field.decimal({
130
- description: "Ease factor before review"
131
- }),
132
- intervalAfter: field.int({ description: "Interval after review (days)" }),
133
- easeFactorAfter: field.decimal({ description: "Ease factor after review" }),
134
- reviewType: field.string({
135
- default: '"review"',
136
- description: "Type: new, learning, review, relearning"
137
- }),
138
- reviewedAt: field.dateTime({ description: "When reviewed" }),
139
- createdAt: field.createdAt(),
140
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
141
- onDelete: "Cascade"
142
- }),
143
- card: field.belongsTo("Card", ["cardId"], ["id"], { onDelete: "Cascade" })
144
- },
145
- indexes: [
146
- index.on(["learnerId", "reviewedAt"]),
147
- index.on(["cardId", "reviewedAt"]),
148
- index.on(["rating"])
149
- ],
150
- enums: [CardRatingEnum]
151
- });
152
- var CardScheduleEntity = defineEntity({
153
- name: "CardSchedule",
154
- description: "SRS schedule for a learner/card pair.",
155
- schema: "lssm_learning",
156
- map: "card_schedule",
157
- fields: {
158
- id: field.id({ description: "Unique schedule identifier" }),
159
- learnerId: field.foreignKey({ description: "Learner" }),
160
- cardId: field.foreignKey({ description: "Card" }),
161
- interval: field.int({
162
- default: 0,
163
- description: "Current interval in days"
164
- }),
165
- easeFactor: field.decimal({
166
- default: 2.5,
167
- description: "Ease factor (SM-2)"
168
- }),
169
- repetitions: field.int({
170
- default: 0,
171
- description: "Number of successful repetitions"
172
- }),
173
- nextReviewAt: field.dateTime({ description: "When next review is due" }),
174
- lastReviewAt: field.dateTime({
175
- isOptional: true,
176
- description: "When last reviewed"
177
- }),
178
- learningStep: field.int({
179
- default: 0,
180
- description: "Current learning step"
181
- }),
182
- isGraduated: field.boolean({
183
- default: false,
184
- description: "Whether card has graduated"
185
- }),
186
- isRelearning: field.boolean({
187
- default: false,
188
- description: "Whether card is being relearned"
189
- }),
190
- lapses: field.int({
191
- default: 0,
192
- description: "Number of times card was forgotten"
193
- }),
194
- reviewCount: field.int({ default: 0, description: "Total review count" }),
195
- createdAt: field.createdAt(),
196
- updatedAt: field.updatedAt(),
197
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
198
- onDelete: "Cascade"
199
- }),
200
- card: field.belongsTo("Card", ["cardId"], ["id"], { onDelete: "Cascade" })
201
- },
202
- indexes: [
203
- index.unique(["learnerId", "cardId"], { name: "card_schedule_unique" }),
204
- index.on(["learnerId", "nextReviewAt"]),
205
- index.on(["nextReviewAt"])
206
- ]
207
- });
208
- var flashcardEntities = [
209
- DeckEntity,
210
- CardEntity,
211
- CardReviewEntity,
212
- CardScheduleEntity
213
- ];
214
- var flashcardEnums = [CardRatingEnum];
215
- export {
216
- flashcardEnums,
217
- flashcardEntities,
218
- DeckEntity,
219
- CardScheduleEntity,
220
- CardReviewEntity,
221
- CardRatingEnum,
222
- CardEntity
223
- };
2
+ import{defineEntity as z,defineEntityEnum as B,field as j,index as q}from"@contractspec/lib.schema";var A=B({name:"CardRating",values:["AGAIN","HARD","GOOD","EASY"],schema:"lssm_learning",description:"Rating for a flashcard review."}),F=z({name:"Deck",description:"A collection of flashcards.",schema:"lssm_learning",map:"deck",fields:{id:j.id({description:"Unique deck identifier"}),ownerId:j.foreignKey({description:"Deck owner (learner)"}),title:j.string({description:"Deck title"}),description:j.string({isOptional:!0,description:"Deck description"}),category:j.string({isOptional:!0,description:"Deck category"}),tags:j.json({isOptional:!0,description:"Tags for discovery"}),isPublic:j.boolean({default:!1,description:"Whether deck is publicly visible"}),cardCount:j.int({default:0,description:"Number of cards"}),coverImageUrl:j.string({isOptional:!0,description:"Cover image URL"}),orgId:j.string({isOptional:!0,description:"Organization scope"}),newCardsPerDay:j.int({default:20,description:"New cards to introduce per day"}),reviewsPerDay:j.int({default:100,description:"Maximum reviews per day"}),metadata:j.json({isOptional:!0,description:"Additional metadata"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),owner:j.belongsTo("Learner",["ownerId"],["id"],{onDelete:"Cascade"}),cards:j.hasMany("Card")},indexes:[q.on(["ownerId"]),q.on(["isPublic","category"]),q.on(["orgId"])]}),G=z({name:"Card",description:"An individual flashcard.",schema:"lssm_learning",map:"card",fields:{id:j.id({description:"Unique card identifier"}),deckId:j.foreignKey({description:"Parent deck"}),front:j.string({description:"Front of card (question)"}),back:j.string({description:"Back of card (answer)"}),hints:j.json({isOptional:!0,description:"Hints for the card"}),explanation:j.string({isOptional:!0,description:"Detailed explanation"}),frontMediaUrl:j.string({isOptional:!0,description:"Media for front"}),backMediaUrl:j.string({isOptional:!0,description:"Media for back"}),audioUrl:j.string({isOptional:!0,description:"Audio pronunciation"}),tags:j.json({isOptional:!0,description:"Card tags"}),difficulty:j.int({default:0,description:"Card difficulty (0-5)"}),order:j.int({default:0,description:"Card order in deck"}),isSuspended:j.boolean({default:!1,description:"Whether card is suspended"}),metadata:j.json({isOptional:!0,description:"Additional metadata"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),deck:j.belongsTo("Deck",["deckId"],["id"],{onDelete:"Cascade"}),reviews:j.hasMany("CardReview"),schedules:j.hasMany("CardSchedule")},indexes:[q.on(["deckId","order"]),q.on(["isSuspended"])]}),H=z({name:"CardReview",description:"A single review of a flashcard.",schema:"lssm_learning",map:"card_review",fields:{id:j.id({description:"Unique review identifier"}),learnerId:j.foreignKey({description:"Reviewer"}),cardId:j.foreignKey({description:"Reviewed card"}),rating:j.enum("CardRating",{description:"Review rating"}),responseTimeMs:j.int({isOptional:!0,description:"Time to respond in ms"}),intervalBefore:j.int({description:"Interval before review (days)"}),easeFactorBefore:j.decimal({description:"Ease factor before review"}),intervalAfter:j.int({description:"Interval after review (days)"}),easeFactorAfter:j.decimal({description:"Ease factor after review"}),reviewType:j.string({default:'"review"',description:"Type: new, learning, review, relearning"}),reviewedAt:j.dateTime({description:"When reviewed"}),createdAt:j.createdAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"}),card:j.belongsTo("Card",["cardId"],["id"],{onDelete:"Cascade"})},indexes:[q.on(["learnerId","reviewedAt"]),q.on(["cardId","reviewedAt"]),q.on(["rating"])],enums:[A]}),I=z({name:"CardSchedule",description:"SRS schedule for a learner/card pair.",schema:"lssm_learning",map:"card_schedule",fields:{id:j.id({description:"Unique schedule identifier"}),learnerId:j.foreignKey({description:"Learner"}),cardId:j.foreignKey({description:"Card"}),interval:j.int({default:0,description:"Current interval in days"}),easeFactor:j.decimal({default:2.5,description:"Ease factor (SM-2)"}),repetitions:j.int({default:0,description:"Number of successful repetitions"}),nextReviewAt:j.dateTime({description:"When next review is due"}),lastReviewAt:j.dateTime({isOptional:!0,description:"When last reviewed"}),learningStep:j.int({default:0,description:"Current learning step"}),isGraduated:j.boolean({default:!1,description:"Whether card has graduated"}),isRelearning:j.boolean({default:!1,description:"Whether card is being relearned"}),lapses:j.int({default:0,description:"Number of times card was forgotten"}),reviewCount:j.int({default:0,description:"Total review count"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"}),card:j.belongsTo("Card",["cardId"],["id"],{onDelete:"Cascade"})},indexes:[q.unique(["learnerId","cardId"],{name:"card_schedule_unique"}),q.on(["learnerId","nextReviewAt"]),q.on(["nextReviewAt"])]}),K=[F,G,H,I],M=[A];export{M as flashcardEnums,K as flashcardEntities,F as DeckEntity,I as CardScheduleEntity,H as CardReviewEntity,A as CardRatingEnum,G as CardEntity};
@@ -1,341 +1,2 @@
1
1
  // @bun
2
- // src/entities/gamification.ts
3
- import {
4
- defineEntity,
5
- defineEntityEnum,
6
- field,
7
- index
8
- } from "@contractspec/lib.schema";
9
- var AchievementTypeEnum = defineEntityEnum({
10
- name: "AchievementType",
11
- values: [
12
- "MILESTONE",
13
- "STREAK",
14
- "SKILL",
15
- "SOCIAL",
16
- "SPECIAL",
17
- "SEASONAL"
18
- ],
19
- schema: "lssm_learning",
20
- description: "Type of achievement."
21
- });
22
- var LeaderboardPeriodEnum = defineEntityEnum({
23
- name: "LeaderboardPeriod",
24
- values: ["DAILY", "WEEKLY", "MONTHLY", "ALL_TIME"],
25
- schema: "lssm_learning",
26
- description: "Leaderboard time period."
27
- });
28
- var AchievementEntity = defineEntity({
29
- name: "Achievement",
30
- description: "An achievement that can be unlocked.",
31
- schema: "lssm_learning",
32
- map: "achievement",
33
- fields: {
34
- id: field.id({ description: "Unique achievement identifier" }),
35
- key: field.string({ isUnique: true, description: "Achievement key" }),
36
- name: field.string({ description: "Achievement name" }),
37
- description: field.string({ description: "Achievement description" }),
38
- icon: field.string({ isOptional: true, description: "Icon name or URL" }),
39
- color: field.string({ isOptional: true, description: "Display color" }),
40
- badgeUrl: field.string({
41
- isOptional: true,
42
- description: "Badge image URL"
43
- }),
44
- type: field.enum("AchievementType", {
45
- default: "MILESTONE",
46
- description: "Achievement type"
47
- }),
48
- category: field.string({
49
- isOptional: true,
50
- description: "Achievement category"
51
- }),
52
- rarity: field.string({
53
- default: '"common"',
54
- description: "Rarity: common, rare, epic, legendary"
55
- }),
56
- xpReward: field.int({ default: 50, description: "XP awarded" }),
57
- condition: field.json({ description: "Unlock condition" }),
58
- order: field.int({ default: 0, description: "Display order" }),
59
- isHidden: field.boolean({
60
- default: false,
61
- description: "Hide until unlocked"
62
- }),
63
- isActive: field.boolean({
64
- default: true,
65
- description: "Whether achievement is active"
66
- }),
67
- orgId: field.string({
68
- isOptional: true,
69
- description: "Organization scope"
70
- }),
71
- metadata: field.json({
72
- isOptional: true,
73
- description: "Additional metadata"
74
- }),
75
- createdAt: field.createdAt(),
76
- updatedAt: field.updatedAt(),
77
- learnerAchievements: field.hasMany("LearnerAchievement")
78
- },
79
- indexes: [
80
- index.on(["type"]),
81
- index.on(["category"]),
82
- index.on(["isActive"]),
83
- index.on(["orgId"])
84
- ],
85
- enums: [AchievementTypeEnum]
86
- });
87
- var LearnerAchievementEntity = defineEntity({
88
- name: "LearnerAchievement",
89
- description: "An achievement unlocked by a learner.",
90
- schema: "lssm_learning",
91
- map: "learner_achievement",
92
- fields: {
93
- id: field.id({ description: "Unique record identifier" }),
94
- learnerId: field.foreignKey({ description: "Learner" }),
95
- achievementId: field.foreignKey({ description: "Achievement" }),
96
- xpEarned: field.int({ default: 0, description: "XP earned" }),
97
- progress: field.int({ default: 100, description: "Progress percentage" }),
98
- currentValue: field.int({
99
- isOptional: true,
100
- description: "Current value towards goal"
101
- }),
102
- targetValue: field.int({
103
- isOptional: true,
104
- description: "Target value for completion"
105
- }),
106
- unlockedAt: field.dateTime({ description: "When unlocked" }),
107
- createdAt: field.createdAt(),
108
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
109
- onDelete: "Cascade"
110
- }),
111
- achievement: field.belongsTo("Achievement", ["achievementId"], ["id"], {
112
- onDelete: "Cascade"
113
- })
114
- },
115
- indexes: [
116
- index.unique(["learnerId", "achievementId"], {
117
- name: "learner_achievement_unique"
118
- }),
119
- index.on(["learnerId", "unlockedAt"]),
120
- index.on(["achievementId"])
121
- ]
122
- });
123
- var StreakEntity = defineEntity({
124
- name: "Streak",
125
- description: "Tracks daily learning streaks.",
126
- schema: "lssm_learning",
127
- map: "streak",
128
- fields: {
129
- id: field.id({ description: "Unique streak identifier" }),
130
- learnerId: field.foreignKey({ description: "Learner" }),
131
- currentStreak: field.int({
132
- default: 0,
133
- description: "Current streak days"
134
- }),
135
- longestStreak: field.int({
136
- default: 0,
137
- description: "Longest streak ever"
138
- }),
139
- lastActivityAt: field.dateTime({
140
- isOptional: true,
141
- description: "Last learning activity"
142
- }),
143
- lastActivityDate: field.string({
144
- isOptional: true,
145
- description: "Last activity date (YYYY-MM-DD)"
146
- }),
147
- freezesRemaining: field.int({
148
- default: 0,
149
- description: "Streak freezes available"
150
- }),
151
- freezeUsedAt: field.dateTime({
152
- isOptional: true,
153
- description: "When last freeze was used"
154
- }),
155
- streakHistory: field.json({
156
- isOptional: true,
157
- description: "Historical streak data"
158
- }),
159
- createdAt: field.createdAt(),
160
- updatedAt: field.updatedAt(),
161
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
162
- onDelete: "Cascade"
163
- })
164
- },
165
- indexes: [
166
- index.unique(["learnerId"], { name: "streak_learner_unique" }),
167
- index.on(["currentStreak"]),
168
- index.on(["longestStreak"])
169
- ]
170
- });
171
- var DailyGoalEntity = defineEntity({
172
- name: "DailyGoal",
173
- description: "Daily XP goal tracking.",
174
- schema: "lssm_learning",
175
- map: "daily_goal",
176
- fields: {
177
- id: field.id({ description: "Unique goal identifier" }),
178
- learnerId: field.foreignKey({ description: "Learner" }),
179
- date: field.string({ description: "Date (YYYY-MM-DD)" }),
180
- targetXp: field.int({ description: "Target XP for the day" }),
181
- currentXp: field.int({ default: 0, description: "XP earned today" }),
182
- isCompleted: field.boolean({
183
- default: false,
184
- description: "Whether goal was met"
185
- }),
186
- completedAt: field.dateTime({
187
- isOptional: true,
188
- description: "When goal was completed"
189
- }),
190
- xpBreakdown: field.json({
191
- isOptional: true,
192
- description: "XP sources breakdown"
193
- }),
194
- createdAt: field.createdAt(),
195
- updatedAt: field.updatedAt(),
196
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
197
- onDelete: "Cascade"
198
- })
199
- },
200
- indexes: [
201
- index.unique(["learnerId", "date"], { name: "daily_goal_unique" }),
202
- index.on(["date", "isCompleted"])
203
- ]
204
- });
205
- var LeaderboardEntryEntity = defineEntity({
206
- name: "LeaderboardEntry",
207
- description: "Leaderboard entry for a learner.",
208
- schema: "lssm_learning",
209
- map: "leaderboard_entry",
210
- fields: {
211
- id: field.id({ description: "Unique entry identifier" }),
212
- learnerId: field.foreignKey({ description: "Learner" }),
213
- periodType: field.enum("LeaderboardPeriod", { description: "Period type" }),
214
- periodKey: field.string({ description: "Period key (e.g., 2024-W01)" }),
215
- xp: field.int({ default: 0, description: "XP earned in period" }),
216
- rank: field.int({ isOptional: true, description: "Rank in leaderboard" }),
217
- lessonsCompleted: field.int({
218
- default: 0,
219
- description: "Lessons completed"
220
- }),
221
- quizzesPassed: field.int({ default: 0, description: "Quizzes passed" }),
222
- cardsReviewed: field.int({ default: 0, description: "Cards reviewed" }),
223
- streakDays: field.int({ default: 0, description: "Streak days in period" }),
224
- league: field.string({ isOptional: true, description: "League tier" }),
225
- orgId: field.string({
226
- isOptional: true,
227
- description: "Organization scope"
228
- }),
229
- createdAt: field.createdAt(),
230
- updatedAt: field.updatedAt(),
231
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
232
- onDelete: "Cascade"
233
- })
234
- },
235
- indexes: [
236
- index.unique(["learnerId", "periodType", "periodKey"], {
237
- name: "leaderboard_entry_unique"
238
- }),
239
- index.on(["periodType", "periodKey", "xp"]),
240
- index.on(["orgId", "periodType", "periodKey", "xp"])
241
- ],
242
- enums: [LeaderboardPeriodEnum]
243
- });
244
- var HeartEntity = defineEntity({
245
- name: "Heart",
246
- description: "Lives/hearts system for quiz attempts.",
247
- schema: "lssm_learning",
248
- map: "heart",
249
- fields: {
250
- id: field.id({ description: "Unique heart record identifier" }),
251
- learnerId: field.foreignKey({ description: "Learner" }),
252
- current: field.int({ default: 5, description: "Current hearts" }),
253
- max: field.int({ default: 5, description: "Maximum hearts" }),
254
- lastRefillAt: field.dateTime({
255
- isOptional: true,
256
- description: "Last refill time"
257
- }),
258
- nextRefillAt: field.dateTime({
259
- isOptional: true,
260
- description: "Next refill time"
261
- }),
262
- refillIntervalMinutes: field.int({
263
- default: 240,
264
- description: "Minutes between refills"
265
- }),
266
- infiniteUntil: field.dateTime({
267
- isOptional: true,
268
- description: "Infinite hearts until"
269
- }),
270
- createdAt: field.createdAt(),
271
- updatedAt: field.updatedAt(),
272
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
273
- onDelete: "Cascade"
274
- })
275
- },
276
- indexes: [
277
- index.unique(["learnerId"], { name: "heart_learner_unique" }),
278
- index.on(["nextRefillAt"])
279
- ]
280
- });
281
- var XPTransactionEntity = defineEntity({
282
- name: "XPTransaction",
283
- description: "Record of XP earned or spent.",
284
- schema: "lssm_learning",
285
- map: "xp_transaction",
286
- fields: {
287
- id: field.id({ description: "Unique transaction identifier" }),
288
- learnerId: field.foreignKey({ description: "Learner" }),
289
- amount: field.int({
290
- description: "XP amount (positive = earned, negative = spent)"
291
- }),
292
- type: field.string({
293
- description: "Transaction type (lesson, quiz, streak, achievement, etc.)"
294
- }),
295
- sourceType: field.string({
296
- isOptional: true,
297
- description: "Source entity type"
298
- }),
299
- sourceId: field.string({
300
- isOptional: true,
301
- description: "Source entity ID"
302
- }),
303
- description: field.string({
304
- isOptional: true,
305
- description: "Human-readable description"
306
- }),
307
- balanceAfter: field.int({ description: "Total XP after transaction" }),
308
- createdAt: field.createdAt(),
309
- learner: field.belongsTo("Learner", ["learnerId"], ["id"], {
310
- onDelete: "Cascade"
311
- })
312
- },
313
- indexes: [
314
- index.on(["learnerId", "createdAt"]),
315
- index.on(["type"]),
316
- index.on(["sourceType", "sourceId"])
317
- ]
318
- });
319
- var gamificationEntities = [
320
- AchievementEntity,
321
- LearnerAchievementEntity,
322
- StreakEntity,
323
- DailyGoalEntity,
324
- LeaderboardEntryEntity,
325
- HeartEntity,
326
- XPTransactionEntity
327
- ];
328
- var gamificationEnums = [AchievementTypeEnum, LeaderboardPeriodEnum];
329
- export {
330
- gamificationEnums,
331
- gamificationEntities,
332
- XPTransactionEntity,
333
- StreakEntity,
334
- LearnerAchievementEntity,
335
- LeaderboardPeriodEnum,
336
- LeaderboardEntryEntity,
337
- HeartEntity,
338
- DailyGoalEntity,
339
- AchievementTypeEnum,
340
- AchievementEntity
341
- };
2
+ import{defineEntity as w,defineEntityEnum as z,field as j,index as q}from"@contractspec/lib.schema";var C=z({name:"AchievementType",values:["MILESTONE","STREAK","SKILL","SOCIAL","SPECIAL","SEASONAL"],schema:"lssm_learning",description:"Type of achievement."}),F=z({name:"LeaderboardPeriod",values:["DAILY","WEEKLY","MONTHLY","ALL_TIME"],schema:"lssm_learning",description:"Leaderboard time period."}),I=w({name:"Achievement",description:"An achievement that can be unlocked.",schema:"lssm_learning",map:"achievement",fields:{id:j.id({description:"Unique achievement identifier"}),key:j.string({isUnique:!0,description:"Achievement key"}),name:j.string({description:"Achievement name"}),description:j.string({description:"Achievement description"}),icon:j.string({isOptional:!0,description:"Icon name or URL"}),color:j.string({isOptional:!0,description:"Display color"}),badgeUrl:j.string({isOptional:!0,description:"Badge image URL"}),type:j.enum("AchievementType",{default:"MILESTONE",description:"Achievement type"}),category:j.string({isOptional:!0,description:"Achievement category"}),rarity:j.string({default:'"common"',description:"Rarity: common, rare, epic, legendary"}),xpReward:j.int({default:50,description:"XP awarded"}),condition:j.json({description:"Unlock condition"}),order:j.int({default:0,description:"Display order"}),isHidden:j.boolean({default:!1,description:"Hide until unlocked"}),isActive:j.boolean({default:!0,description:"Whether achievement is active"}),orgId:j.string({isOptional:!0,description:"Organization scope"}),metadata:j.json({isOptional:!0,description:"Additional metadata"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),learnerAchievements:j.hasMany("LearnerAchievement")},indexes:[q.on(["type"]),q.on(["category"]),q.on(["isActive"]),q.on(["orgId"])],enums:[C]}),J=w({name:"LearnerAchievement",description:"An achievement unlocked by a learner.",schema:"lssm_learning",map:"learner_achievement",fields:{id:j.id({description:"Unique record identifier"}),learnerId:j.foreignKey({description:"Learner"}),achievementId:j.foreignKey({description:"Achievement"}),xpEarned:j.int({default:0,description:"XP earned"}),progress:j.int({default:100,description:"Progress percentage"}),currentValue:j.int({isOptional:!0,description:"Current value towards goal"}),targetValue:j.int({isOptional:!0,description:"Target value for completion"}),unlockedAt:j.dateTime({description:"When unlocked"}),createdAt:j.createdAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"}),achievement:j.belongsTo("Achievement",["achievementId"],["id"],{onDelete:"Cascade"})},indexes:[q.unique(["learnerId","achievementId"],{name:"learner_achievement_unique"}),q.on(["learnerId","unlockedAt"]),q.on(["achievementId"])]}),K=w({name:"Streak",description:"Tracks daily learning streaks.",schema:"lssm_learning",map:"streak",fields:{id:j.id({description:"Unique streak identifier"}),learnerId:j.foreignKey({description:"Learner"}),currentStreak:j.int({default:0,description:"Current streak days"}),longestStreak:j.int({default:0,description:"Longest streak ever"}),lastActivityAt:j.dateTime({isOptional:!0,description:"Last learning activity"}),lastActivityDate:j.string({isOptional:!0,description:"Last activity date (YYYY-MM-DD)"}),freezesRemaining:j.int({default:0,description:"Streak freezes available"}),freezeUsedAt:j.dateTime({isOptional:!0,description:"When last freeze was used"}),streakHistory:j.json({isOptional:!0,description:"Historical streak data"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"})},indexes:[q.unique(["learnerId"],{name:"streak_learner_unique"}),q.on(["currentStreak"]),q.on(["longestStreak"])]}),M=w({name:"DailyGoal",description:"Daily XP goal tracking.",schema:"lssm_learning",map:"daily_goal",fields:{id:j.id({description:"Unique goal identifier"}),learnerId:j.foreignKey({description:"Learner"}),date:j.string({description:"Date (YYYY-MM-DD)"}),targetXp:j.int({description:"Target XP for the day"}),currentXp:j.int({default:0,description:"XP earned today"}),isCompleted:j.boolean({default:!1,description:"Whether goal was met"}),completedAt:j.dateTime({isOptional:!0,description:"When goal was completed"}),xpBreakdown:j.json({isOptional:!0,description:"XP sources breakdown"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"})},indexes:[q.unique(["learnerId","date"],{name:"daily_goal_unique"}),q.on(["date","isCompleted"])]}),N=w({name:"LeaderboardEntry",description:"Leaderboard entry for a learner.",schema:"lssm_learning",map:"leaderboard_entry",fields:{id:j.id({description:"Unique entry identifier"}),learnerId:j.foreignKey({description:"Learner"}),periodType:j.enum("LeaderboardPeriod",{description:"Period type"}),periodKey:j.string({description:"Period key (e.g., 2024-W01)"}),xp:j.int({default:0,description:"XP earned in period"}),rank:j.int({isOptional:!0,description:"Rank in leaderboard"}),lessonsCompleted:j.int({default:0,description:"Lessons completed"}),quizzesPassed:j.int({default:0,description:"Quizzes passed"}),cardsReviewed:j.int({default:0,description:"Cards reviewed"}),streakDays:j.int({default:0,description:"Streak days in period"}),league:j.string({isOptional:!0,description:"League tier"}),orgId:j.string({isOptional:!0,description:"Organization scope"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"})},indexes:[q.unique(["learnerId","periodType","periodKey"],{name:"leaderboard_entry_unique"}),q.on(["periodType","periodKey","xp"]),q.on(["orgId","periodType","periodKey","xp"])],enums:[F]}),O=w({name:"Heart",description:"Lives/hearts system for quiz attempts.",schema:"lssm_learning",map:"heart",fields:{id:j.id({description:"Unique heart record identifier"}),learnerId:j.foreignKey({description:"Learner"}),current:j.int({default:5,description:"Current hearts"}),max:j.int({default:5,description:"Maximum hearts"}),lastRefillAt:j.dateTime({isOptional:!0,description:"Last refill time"}),nextRefillAt:j.dateTime({isOptional:!0,description:"Next refill time"}),refillIntervalMinutes:j.int({default:240,description:"Minutes between refills"}),infiniteUntil:j.dateTime({isOptional:!0,description:"Infinite hearts until"}),createdAt:j.createdAt(),updatedAt:j.updatedAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"})},indexes:[q.unique(["learnerId"],{name:"heart_learner_unique"}),q.on(["nextRefillAt"])]}),Q=w({name:"XPTransaction",description:"Record of XP earned or spent.",schema:"lssm_learning",map:"xp_transaction",fields:{id:j.id({description:"Unique transaction identifier"}),learnerId:j.foreignKey({description:"Learner"}),amount:j.int({description:"XP amount (positive = earned, negative = spent)"}),type:j.string({description:"Transaction type (lesson, quiz, streak, achievement, etc.)"}),sourceType:j.string({isOptional:!0,description:"Source entity type"}),sourceId:j.string({isOptional:!0,description:"Source entity ID"}),description:j.string({isOptional:!0,description:"Human-readable description"}),balanceAfter:j.int({description:"Total XP after transaction"}),createdAt:j.createdAt(),learner:j.belongsTo("Learner",["learnerId"],["id"],{onDelete:"Cascade"})},indexes:[q.on(["learnerId","createdAt"]),q.on(["type"]),q.on(["sourceType","sourceId"])]}),V=[I,J,K,M,N,O,Q],W=[C,F];export{W as gamificationEnums,V as gamificationEntities,Q as XPTransactionEntity,K as StreakEntity,J as LearnerAchievementEntity,F as LeaderboardPeriodEnum,N as LeaderboardEntryEntity,O as HeartEntity,M as DailyGoalEntity,C as AchievementTypeEnum,I as AchievementEntity};