@contractspec/module.learning-journey 3.7.15 → 3.7.17
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 +1 -578
- package/dist/browser/contracts/models.js +1 -193
- package/dist/browser/contracts/onboarding.js +1 -417
- package/dist/browser/contracts/operations.js +1 -326
- package/dist/browser/contracts/shared.js +1 -5
- package/dist/browser/docs/index.js +7 -51
- package/dist/browser/docs/learning-journey.docblock.js +7 -51
- package/dist/browser/engines/index.js +1 -675
- package/dist/browser/engines/srs.js +1 -198
- package/dist/browser/engines/streak.js +1 -159
- package/dist/browser/engines/xp.js +1 -320
- package/dist/browser/entities/ai.js +1 -343
- package/dist/browser/entities/course.js +1 -276
- package/dist/browser/entities/flashcard.js +1 -222
- package/dist/browser/entities/gamification.js +1 -340
- package/dist/browser/entities/index.js +1 -2140
- package/dist/browser/entities/learner.js +1 -333
- package/dist/browser/entities/onboarding.js +1 -301
- package/dist/browser/entities/quiz.js +1 -304
- package/dist/browser/events.js +1 -423
- package/dist/browser/i18n/catalogs/en.js +1 -43
- package/dist/browser/i18n/catalogs/es.js +1 -43
- package/dist/browser/i18n/catalogs/fr.js +1 -43
- package/dist/browser/i18n/catalogs/index.js +1 -127
- package/dist/browser/i18n/index.js +1 -169
- package/dist/browser/i18n/keys.js +1 -16
- package/dist/browser/i18n/locale.js +1 -13
- package/dist/browser/i18n/messages.js +1 -139
- package/dist/browser/index.js +7 -3914
- package/dist/browser/learning-journey.capability.js +1 -43
- package/dist/browser/learning-journey.feature.js +1 -56
- package/dist/contracts/index.js +1 -578
- package/dist/contracts/models.js +1 -193
- package/dist/contracts/onboarding.js +1 -417
- package/dist/contracts/operations.js +1 -326
- package/dist/contracts/shared.js +1 -5
- package/dist/docs/index.js +7 -51
- package/dist/docs/learning-journey.docblock.js +7 -51
- package/dist/engines/index.js +1 -675
- package/dist/engines/srs.js +1 -198
- package/dist/engines/streak.js +1 -159
- package/dist/engines/xp.js +1 -320
- package/dist/entities/ai.js +1 -343
- package/dist/entities/course.js +1 -276
- package/dist/entities/flashcard.js +1 -222
- package/dist/entities/gamification.js +1 -340
- package/dist/entities/index.js +1 -2140
- package/dist/entities/learner.js +1 -333
- package/dist/entities/onboarding.js +1 -301
- package/dist/entities/quiz.js +1 -304
- package/dist/events.js +1 -423
- package/dist/i18n/catalogs/en.js +1 -43
- package/dist/i18n/catalogs/es.js +1 -43
- package/dist/i18n/catalogs/fr.js +1 -43
- package/dist/i18n/catalogs/index.js +1 -127
- package/dist/i18n/index.js +1 -169
- package/dist/i18n/keys.js +1 -16
- package/dist/i18n/locale.js +1 -13
- package/dist/i18n/messages.js +1 -139
- package/dist/index.js +7 -3914
- package/dist/learning-journey.capability.js +1 -43
- package/dist/learning-journey.feature.js +1 -56
- package/dist/node/contracts/index.js +1 -578
- package/dist/node/contracts/models.js +1 -193
- package/dist/node/contracts/onboarding.js +1 -417
- package/dist/node/contracts/operations.js +1 -326
- package/dist/node/contracts/shared.js +1 -5
- package/dist/node/docs/index.js +7 -51
- package/dist/node/docs/learning-journey.docblock.js +7 -51
- package/dist/node/engines/index.js +1 -675
- package/dist/node/engines/srs.js +1 -198
- package/dist/node/engines/streak.js +1 -159
- package/dist/node/engines/xp.js +1 -320
- package/dist/node/entities/ai.js +1 -343
- package/dist/node/entities/course.js +1 -276
- package/dist/node/entities/flashcard.js +1 -222
- package/dist/node/entities/gamification.js +1 -340
- package/dist/node/entities/index.js +1 -2140
- package/dist/node/entities/learner.js +1 -333
- package/dist/node/entities/onboarding.js +1 -301
- package/dist/node/entities/quiz.js +1 -304
- package/dist/node/events.js +1 -423
- package/dist/node/i18n/catalogs/en.js +1 -43
- package/dist/node/i18n/catalogs/es.js +1 -43
- package/dist/node/i18n/catalogs/fr.js +1 -43
- package/dist/node/i18n/catalogs/index.js +1 -127
- package/dist/node/i18n/index.js +1 -169
- package/dist/node/i18n/keys.js +1 -16
- package/dist/node/i18n/locale.js +1 -13
- package/dist/node/i18n/messages.js +1 -139
- package/dist/node/index.js +7 -3914
- package/dist/node/learning-journey.capability.js +1 -43
- package/dist/node/learning-journey.feature.js +1 -56
- package/package.json +7 -7
|
@@ -1,223 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
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
|
-
|
|
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};
|