@vue-skuilder/db 0.1.11 → 0.1.12
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/core/index.d.mts +7 -6
- package/dist/core/index.d.ts +7 -6
- package/dist/core/index.js +146 -37
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +146 -37
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-VieuAAkV.d.mts → dataLayerProvider-BiP3kWix.d.mts} +1 -1
- package/dist/{dataLayerProvider-juuqUHOP.d.ts → dataLayerProvider-DSdeyRT3.d.ts} +1 -1
- package/dist/impl/couch/index.d.mts +3 -3
- package/dist/impl/couch/index.d.ts +3 -3
- package/dist/impl/couch/index.js +146 -37
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +146 -37
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.mts +14 -6
- package/dist/impl/static/index.d.ts +14 -6
- package/dist/impl/static/index.js +147 -39
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +147 -39
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/{index-DZyxHCcf.d.mts → index-Bmll7Xse.d.mts} +1 -1
- package/dist/{index-CWY6yhkV.d.ts → index-CD8BZz2k.d.ts} +1 -1
- package/dist/index.d.mts +119 -24
- package/dist/index.d.ts +119 -24
- package/dist/index.js +785 -261
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +789 -265
- package/dist/index.mjs.map +1 -1
- package/dist/{types-DtoI27Xh.d.ts → types-CewsN87z.d.ts} +1 -1
- package/dist/{types-Che4wTwA.d.mts → types-Dbp5DaRR.d.mts} +1 -1
- package/dist/{types-legacy-B8ahaCbj.d.mts → types-legacy-6ettoclI.d.mts} +13 -2
- package/dist/{types-legacy-B8ahaCbj.d.ts → types-legacy-6ettoclI.d.ts} +13 -2
- package/dist/{userDB-DJ8HMw83.d.mts → userDB-C4yyAnpp.d.mts} +3 -3
- package/dist/{userDB-B7zTQ123.d.ts → userDB-CD6s6ZCp.d.ts} +3 -3
- package/dist/util/packer/index.d.mts +3 -3
- package/dist/util/packer/index.d.ts +3 -3
- package/package.json +3 -3
- package/src/core/navigators/hardcodedOrder.ts +64 -0
- package/src/core/navigators/index.ts +1 -0
- package/src/core/types/contentNavigationStrategy.ts +2 -1
- package/src/core/types/types-legacy.ts +2 -2
- package/src/impl/common/BaseUserDB.ts +15 -11
- package/src/impl/couch/courseDB.ts +74 -27
- package/src/impl/couch/updateQueue.ts +8 -3
- package/src/impl/static/StaticDataLayerProvider.ts +57 -17
- package/src/impl/static/courseDB.ts +17 -12
- package/src/impl/static/coursesDB.ts +10 -6
- package/src/study/ItemQueue.ts +58 -0
- package/src/study/SessionController.ts +132 -178
- package/src/study/services/CardHydrationService.ts +153 -0
- package/src/study/services/EloService.ts +85 -0
- package/src/study/services/ResponseProcessor.ts +224 -0
- package/src/study/services/SrsService.ts +44 -0
package/dist/core/index.mjs
CHANGED
|
@@ -320,7 +320,9 @@ var init_updateQueue = __esm({
|
|
|
320
320
|
async applyUpdates(id) {
|
|
321
321
|
logger.debug(`Applying updates on doc: ${id}`);
|
|
322
322
|
if (this.inprogressUpdates[id]) {
|
|
323
|
-
|
|
323
|
+
while (this.inprogressUpdates[id]) {
|
|
324
|
+
await new Promise((resolve) => setTimeout(resolve, Math.random() * 50));
|
|
325
|
+
}
|
|
324
326
|
return this.applyUpdates(id);
|
|
325
327
|
} else {
|
|
326
328
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
@@ -356,6 +358,9 @@ var init_updateQueue = __esm({
|
|
|
356
358
|
if (e.name === "conflict" && i < MAX_RETRIES - 1) {
|
|
357
359
|
logger.warn(`Conflict on update for doc ${id}, retry #${i + 1}`);
|
|
358
360
|
await new Promise((res) => setTimeout(res, 50 * Math.random()));
|
|
361
|
+
} else if (e.name === "not_found" && i === 0) {
|
|
362
|
+
logger.warn(`Update failed for ${id} - does not exist. Throwing to caller.`);
|
|
363
|
+
throw e;
|
|
359
364
|
} else {
|
|
360
365
|
delete this.inprogressUpdates[id];
|
|
361
366
|
if (this.pendingUpdates[id]) {
|
|
@@ -721,12 +726,74 @@ var init_elo = __esm({
|
|
|
721
726
|
}
|
|
722
727
|
});
|
|
723
728
|
|
|
729
|
+
// src/core/navigators/hardcodedOrder.ts
|
|
730
|
+
var hardcodedOrder_exports = {};
|
|
731
|
+
__export(hardcodedOrder_exports, {
|
|
732
|
+
default: () => HardcodedOrderNavigator
|
|
733
|
+
});
|
|
734
|
+
var HardcodedOrderNavigator;
|
|
735
|
+
var init_hardcodedOrder = __esm({
|
|
736
|
+
"src/core/navigators/hardcodedOrder.ts"() {
|
|
737
|
+
"use strict";
|
|
738
|
+
init_navigators();
|
|
739
|
+
init_logger();
|
|
740
|
+
HardcodedOrderNavigator = class extends ContentNavigator {
|
|
741
|
+
orderedCardIds = [];
|
|
742
|
+
user;
|
|
743
|
+
course;
|
|
744
|
+
constructor(user, course, strategyData) {
|
|
745
|
+
super();
|
|
746
|
+
this.user = user;
|
|
747
|
+
this.course = course;
|
|
748
|
+
if (strategyData.serializedData) {
|
|
749
|
+
try {
|
|
750
|
+
this.orderedCardIds = JSON.parse(strategyData.serializedData);
|
|
751
|
+
} catch (e) {
|
|
752
|
+
logger.error("Failed to parse serializedData for HardcodedOrderNavigator", e);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
async getPendingReviews() {
|
|
757
|
+
const reviews = await this.user.getPendingReviews(this.course.getCourseID());
|
|
758
|
+
return reviews.map((r) => {
|
|
759
|
+
return {
|
|
760
|
+
...r,
|
|
761
|
+
contentSourceType: "course",
|
|
762
|
+
contentSourceID: this.course.getCourseID(),
|
|
763
|
+
cardID: r.cardId,
|
|
764
|
+
courseID: r.courseId,
|
|
765
|
+
reviewID: r._id,
|
|
766
|
+
status: "review"
|
|
767
|
+
};
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
async getNewCards(limit = 99) {
|
|
771
|
+
const activeCardIds = (await this.user.getActiveCards()).map((c) => c.cardID);
|
|
772
|
+
const newCardIds = this.orderedCardIds.filter(
|
|
773
|
+
(cardId) => !activeCardIds.includes(cardId)
|
|
774
|
+
);
|
|
775
|
+
const cardsToReturn = newCardIds.slice(0, limit);
|
|
776
|
+
return cardsToReturn.map((cardId) => {
|
|
777
|
+
return {
|
|
778
|
+
cardID: cardId,
|
|
779
|
+
courseID: this.course.getCourseID(),
|
|
780
|
+
contentSourceType: "course",
|
|
781
|
+
contentSourceID: this.course.getCourseID(),
|
|
782
|
+
status: "new"
|
|
783
|
+
};
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
|
|
724
790
|
// import("./**/*") in src/core/navigators/index.ts
|
|
725
791
|
var globImport;
|
|
726
792
|
var init_ = __esm({
|
|
727
793
|
'import("./**/*") in src/core/navigators/index.ts'() {
|
|
728
794
|
globImport = __glob({
|
|
729
795
|
"./elo.ts": () => Promise.resolve().then(() => (init_elo(), elo_exports)),
|
|
796
|
+
"./hardcodedOrder.ts": () => Promise.resolve().then(() => (init_hardcodedOrder(), hardcodedOrder_exports)),
|
|
730
797
|
"./index.ts": () => Promise.resolve().then(() => (init_navigators(), navigators_exports))
|
|
731
798
|
});
|
|
732
799
|
}
|
|
@@ -746,6 +813,7 @@ var init_navigators = __esm({
|
|
|
746
813
|
init_();
|
|
747
814
|
Navigators = /* @__PURE__ */ ((Navigators2) => {
|
|
748
815
|
Navigators2["ELO"] = "elo";
|
|
816
|
+
Navigators2["HARDCODED"] = "hardcodedOrder";
|
|
749
817
|
return Navigators2;
|
|
750
818
|
})(Navigators || {});
|
|
751
819
|
ContentNavigator = class {
|
|
@@ -975,6 +1043,23 @@ var init_courseDB = __esm({
|
|
|
975
1043
|
if (!doc.docType || !(doc.docType === "CARD" /* CARD */)) {
|
|
976
1044
|
throw new Error(`failed to remove ${id} from course ${this.id}. id does not point to a card`);
|
|
977
1045
|
}
|
|
1046
|
+
try {
|
|
1047
|
+
const appliedTags = await this.getAppliedTags(id);
|
|
1048
|
+
const results = await Promise.allSettled(
|
|
1049
|
+
appliedTags.rows.map(async (tagRow) => {
|
|
1050
|
+
const tagId = tagRow.id;
|
|
1051
|
+
await this.removeTagFromCard(id, tagId);
|
|
1052
|
+
})
|
|
1053
|
+
);
|
|
1054
|
+
results.forEach((result, index) => {
|
|
1055
|
+
if (result.status === "rejected") {
|
|
1056
|
+
const tagId = appliedTags.rows[index].id;
|
|
1057
|
+
logger.error(`Failed to remove card ${id} from tag ${tagId}: ${result.reason}`);
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
logger.error(`Error removing card ${id} from tags: ${error}`);
|
|
1062
|
+
}
|
|
978
1063
|
return this.db.remove(doc);
|
|
979
1064
|
}
|
|
980
1065
|
async getCardDisplayableDataIDs(id) {
|
|
@@ -1158,23 +1243,9 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1158
1243
|
////////////////////////////////////
|
|
1159
1244
|
getNavigationStrategy(id) {
|
|
1160
1245
|
logger.debug(`[courseDB] Getting navigation strategy: ${id}`);
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
name: "ELO",
|
|
1165
|
-
description: "ELO-based navigation strategy for ordering content by difficulty",
|
|
1166
|
-
implementingClass: "elo" /* ELO */,
|
|
1167
|
-
course: this.id,
|
|
1168
|
-
serializedData: ""
|
|
1169
|
-
// serde is a noop for ELO navigator.
|
|
1170
|
-
};
|
|
1171
|
-
return Promise.resolve(strategy);
|
|
1172
|
-
}
|
|
1173
|
-
getAllNavigationStrategies() {
|
|
1174
|
-
logger.debug("[courseDB] Returning hard-coded navigation strategies");
|
|
1175
|
-
const strategies = [
|
|
1176
|
-
{
|
|
1177
|
-
id: "ELO",
|
|
1246
|
+
if (id == "") {
|
|
1247
|
+
const strategy = {
|
|
1248
|
+
_id: "NAVIGATION_STRATEGY-ELO",
|
|
1178
1249
|
docType: "NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */,
|
|
1179
1250
|
name: "ELO",
|
|
1180
1251
|
description: "ELO-based navigation strategy for ordering content by difficulty",
|
|
@@ -1182,14 +1253,25 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1182
1253
|
course: this.id,
|
|
1183
1254
|
serializedData: ""
|
|
1184
1255
|
// serde is a noop for ELO navigator.
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1256
|
+
};
|
|
1257
|
+
return Promise.resolve(strategy);
|
|
1258
|
+
} else {
|
|
1259
|
+
return this.db.get(id);
|
|
1260
|
+
}
|
|
1188
1261
|
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1262
|
+
async getAllNavigationStrategies() {
|
|
1263
|
+
const prefix = DocTypePrefixes["NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */];
|
|
1264
|
+
const result = await this.db.allDocs({
|
|
1265
|
+
startkey: prefix,
|
|
1266
|
+
endkey: `${prefix}\uFFF0`,
|
|
1267
|
+
include_docs: true
|
|
1268
|
+
});
|
|
1269
|
+
return result.rows.map((row) => row.doc);
|
|
1270
|
+
}
|
|
1271
|
+
async addNavigationStrategy(data) {
|
|
1272
|
+
logger.debug(`[courseDB] Adding navigation strategy: ${data._id}`);
|
|
1273
|
+
return this.db.put(data).then(() => {
|
|
1274
|
+
});
|
|
1193
1275
|
}
|
|
1194
1276
|
updateNavigationStrategy(id, data) {
|
|
1195
1277
|
logger.debug(`[courseDB] Updating navigation strategy: ${id}`);
|
|
@@ -1197,9 +1279,32 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1197
1279
|
return Promise.resolve();
|
|
1198
1280
|
}
|
|
1199
1281
|
async surfaceNavigationStrategy() {
|
|
1282
|
+
try {
|
|
1283
|
+
const config = await this.getCourseConfig();
|
|
1284
|
+
if (config.defaultNavigationStrategyId) {
|
|
1285
|
+
try {
|
|
1286
|
+
const strategy = await this.getNavigationStrategy(config.defaultNavigationStrategyId);
|
|
1287
|
+
if (strategy) {
|
|
1288
|
+
logger.debug(`Surfacing strategy ${strategy.name} from course config`);
|
|
1289
|
+
return strategy;
|
|
1290
|
+
}
|
|
1291
|
+
} catch (e) {
|
|
1292
|
+
logger.warn(
|
|
1293
|
+
// @ts-expect-error tmp: defaultNavigationStrategyId property does not yet exist
|
|
1294
|
+
`Failed to load strategy '${config.defaultNavigationStrategyId}' specified in course config. Falling back to ELO.`,
|
|
1295
|
+
e
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
} catch (e) {
|
|
1300
|
+
logger.warn(
|
|
1301
|
+
"Could not retrieve course config to determine navigation strategy. Falling back to ELO.",
|
|
1302
|
+
e
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1200
1305
|
logger.warn(`Returning hard-coded default ELO navigator`);
|
|
1201
1306
|
const ret = {
|
|
1202
|
-
|
|
1307
|
+
_id: "NAVIGATION_STRATEGY-ELO",
|
|
1203
1308
|
docType: "NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */,
|
|
1204
1309
|
name: "ELO",
|
|
1205
1310
|
description: "ELO-based navigation strategy",
|
|
@@ -2319,17 +2424,21 @@ Currently logged-in as ${this._username}.`
|
|
|
2319
2424
|
} catch (e) {
|
|
2320
2425
|
const reason = e;
|
|
2321
2426
|
if (reason.status === 404) {
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2427
|
+
try {
|
|
2428
|
+
const initCardHistory = {
|
|
2429
|
+
_id: cardHistoryID,
|
|
2430
|
+
cardID: record.cardID,
|
|
2431
|
+
courseID: record.courseID,
|
|
2432
|
+
records: [record],
|
|
2433
|
+
lapses: 0,
|
|
2434
|
+
streak: 0,
|
|
2435
|
+
bestInterval: 0
|
|
2436
|
+
};
|
|
2437
|
+
const putResult = await this.writeDB.put(initCardHistory);
|
|
2438
|
+
return { ...initCardHistory, _rev: putResult.rev };
|
|
2439
|
+
} catch (creationError) {
|
|
2440
|
+
throw new Error(`Failed to create CardHistory for ${cardHistoryID}. Reason: ${creationError}`);
|
|
2441
|
+
}
|
|
2333
2442
|
} else {
|
|
2334
2443
|
throw new Error(`putCardRecord failed because of:
|
|
2335
2444
|
name:${reason.name}
|