@vue-skuilder/db 0.1.11-9 → 0.1.11
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 +5 -5
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +212 -50
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +212 -50
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-DqtNroSh.d.ts → dataLayerProvider-VieuAAkV.d.mts} +8 -1
- package/dist/{dataLayerProvider-BInqI_RF.d.mts → dataLayerProvider-juuqUHOP.d.ts} +8 -1
- package/dist/impl/couch/index.d.mts +19 -7
- package/dist/impl/couch/index.d.ts +19 -7
- package/dist/impl/couch/index.js +229 -63
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +228 -62
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.mts +13 -6
- package/dist/impl/static/index.d.ts +13 -6
- package/dist/impl/static/index.js +142 -46
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +142 -46
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/{index-CLL31bEy.d.ts → index-CWY6yhkV.d.ts} +1 -1
- package/dist/{index-CUNnL38E.d.mts → index-DZyxHCcf.d.mts} +1 -1
- package/dist/index.d.mts +28 -20
- package/dist/index.d.ts +28 -20
- package/dist/index.js +374 -108
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +378 -108
- package/dist/index.mjs.map +1 -1
- package/dist/pouch/index.d.mts +1 -0
- package/dist/pouch/index.d.ts +1 -0
- package/dist/pouch/index.js +49 -0
- package/dist/pouch/index.js.map +1 -0
- package/dist/pouch/index.mjs +16 -0
- package/dist/pouch/index.mjs.map +1 -0
- package/dist/{types-DC-ckZug.d.mts → types-Che4wTwA.d.mts} +1 -1
- package/dist/{types-BefDGkKa.d.ts → types-DtoI27Xh.d.ts} +1 -1
- package/dist/{types-legacy-Birv-Jx6.d.mts → types-legacy-B8ahaCbj.d.mts} +5 -1
- package/dist/{types-legacy-Birv-Jx6.d.ts → types-legacy-B8ahaCbj.d.ts} +5 -1
- package/dist/{userDB-C33Hzjgn.d.mts → userDB-B7zTQ123.d.ts} +88 -55
- package/dist/{userDB-DusL7OXe.d.ts → userDB-DJ8HMw83.d.mts} +88 -55
- 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/interfaces/contentSource.ts +3 -2
- package/src/core/interfaces/courseDB.ts +26 -3
- package/src/core/interfaces/dataLayerProvider.ts +9 -1
- package/src/core/interfaces/userDB.ts +80 -64
- package/src/core/navigators/elo.ts +10 -7
- package/src/core/navigators/index.ts +1 -1
- package/src/core/types/types-legacy.ts +5 -0
- package/src/impl/common/BaseUserDB.ts +45 -3
- package/src/impl/couch/CouchDBSyncStrategy.ts +2 -2
- package/src/impl/couch/PouchDataLayerProvider.ts +21 -0
- package/src/impl/couch/adminDB.ts +2 -2
- package/src/impl/couch/auth.ts +13 -4
- package/src/impl/couch/classroomDB.ts +10 -12
- package/src/impl/couch/courseAPI.ts +2 -2
- package/src/impl/couch/courseDB.ts +130 -11
- package/src/impl/couch/courseLookupDB.ts +4 -3
- package/src/impl/couch/index.ts +36 -4
- package/src/impl/couch/pouchdb-setup.ts +3 -3
- package/src/impl/couch/updateQueue.ts +51 -33
- package/src/impl/static/StaticDataLayerProvider.ts +11 -0
- package/src/impl/static/courseDB.ts +47 -8
- package/src/pouch/index.ts +2 -0
- package/src/study/SessionController.ts +168 -51
- package/src/study/SpacedRepetition.ts +1 -1
- package/tsup.config.ts +1 -0
package/dist/core/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
export { D as DataLayerProvider } from '../dataLayerProvider-
|
|
4
|
-
import {
|
|
5
|
-
export { b as CardData, c as CourseListData, e as DataShapeData, d as DisplayableData, D as DocType,
|
|
1
|
+
import { i as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard, S as StudySessionNewItem } from '../userDB-DJ8HMw83.mjs';
|
|
2
|
+
export { G as ActivityRecord, A as AdminDBInterface, t as AssignedCard, h as AssignedContent, s as AssignedCourse, r as AssignedTag, c as ClassroomDBInterface, B as ClassroomRegistration, z as ClassroomRegistrationDesignation, E as ClassroomRegistrationDoc, p as ContentSourceID, d as CourseInfo, H as CourseRegistration, I as CourseRegistrationDoc, b as CoursesDBInterface, j as StudentClassroomDBInterface, l as StudySessionFailedItem, m as StudySessionFailedNewItem, n as StudySessionFailedReviewItem, k as StudySessionItem, T as TeacherClassroomDBInterface, F as UserConfig, x as UserCourseSetting, w as UserCourseSettings, v as UserDBAuthenticator, a as UserDBReader, u as UserDBWriter, y as UsrCrsDataInterface, q as getStudySource, o as isReview } from '../userDB-DJ8HMw83.mjs';
|
|
3
|
+
export { D as DataLayerProvider } from '../dataLayerProvider-VieuAAkV.mjs';
|
|
4
|
+
import { h as CardHistory, C as CardRecord, i as QuestionRecord } from '../types-legacy-B8ahaCbj.mjs';
|
|
5
|
+
export { b as CardData, c as CourseListData, e as DataShapeData, d as DisplayableData, D as DocType, g as DocTypePrefixes, F as Field, G as GuestUsername, Q as QualifiedCardID, f as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-B8ahaCbj.mjs';
|
|
6
6
|
import { DataShape, ParsedCard } from '@vue-skuilder/common';
|
|
7
7
|
import 'moment';
|
|
8
8
|
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
export { D as DataLayerProvider } from '../dataLayerProvider-
|
|
4
|
-
import {
|
|
5
|
-
export { b as CardData, c as CourseListData, e as DataShapeData, d as DisplayableData, D as DocType,
|
|
1
|
+
import { i as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard, S as StudySessionNewItem } from '../userDB-B7zTQ123.js';
|
|
2
|
+
export { G as ActivityRecord, A as AdminDBInterface, t as AssignedCard, h as AssignedContent, s as AssignedCourse, r as AssignedTag, c as ClassroomDBInterface, B as ClassroomRegistration, z as ClassroomRegistrationDesignation, E as ClassroomRegistrationDoc, p as ContentSourceID, d as CourseInfo, H as CourseRegistration, I as CourseRegistrationDoc, b as CoursesDBInterface, j as StudentClassroomDBInterface, l as StudySessionFailedItem, m as StudySessionFailedNewItem, n as StudySessionFailedReviewItem, k as StudySessionItem, T as TeacherClassroomDBInterface, F as UserConfig, x as UserCourseSetting, w as UserCourseSettings, v as UserDBAuthenticator, a as UserDBReader, u as UserDBWriter, y as UsrCrsDataInterface, q as getStudySource, o as isReview } from '../userDB-B7zTQ123.js';
|
|
3
|
+
export { D as DataLayerProvider } from '../dataLayerProvider-juuqUHOP.js';
|
|
4
|
+
import { h as CardHistory, C as CardRecord, i as QuestionRecord } from '../types-legacy-B8ahaCbj.js';
|
|
5
|
+
export { b as CardData, c as CourseListData, e as DataShapeData, d as DisplayableData, D as DocType, g as DocTypePrefixes, F as Field, G as GuestUsername, Q as QualifiedCardID, f as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-B8ahaCbj.js';
|
|
6
6
|
import { DataShape, ParsedCard } from '@vue-skuilder/common';
|
|
7
7
|
import 'moment';
|
|
8
8
|
|
package/dist/core/index.js
CHANGED
|
@@ -187,9 +187,9 @@ var init_pouchdb_setup = __esm({
|
|
|
187
187
|
import_pouchdb.default.plugin(import_pouchdb_find.default);
|
|
188
188
|
import_pouchdb.default.plugin(import_pouchdb_authentication.default);
|
|
189
189
|
import_pouchdb.default.defaults({
|
|
190
|
-
ajax: {
|
|
191
|
-
|
|
192
|
-
}
|
|
190
|
+
// ajax: {
|
|
191
|
+
// timeout: 60000,
|
|
192
|
+
// },
|
|
193
193
|
});
|
|
194
194
|
pouchdb_setup_default = import_pouchdb.default;
|
|
195
195
|
}
|
|
@@ -348,37 +348,48 @@ var init_updateQueue = __esm({
|
|
|
348
348
|
} else {
|
|
349
349
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
350
350
|
this.inprogressUpdates[id] = true;
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
351
|
+
const MAX_RETRIES = 5;
|
|
352
|
+
for (let i = 0; i < MAX_RETRIES; i++) {
|
|
353
|
+
try {
|
|
354
|
+
const doc = await this.readDB.get(id);
|
|
355
|
+
logger.debug(`Retrieved doc: ${id}`);
|
|
356
|
+
let updatedDoc = { ...doc };
|
|
357
|
+
const updatesToApply = [...this.pendingUpdates[id]];
|
|
358
|
+
for (const update of updatesToApply) {
|
|
359
|
+
if (typeof update === "function") {
|
|
360
|
+
updatedDoc = { ...updatedDoc, ...update(updatedDoc) };
|
|
361
|
+
} else {
|
|
362
|
+
updatedDoc = {
|
|
363
|
+
...updatedDoc,
|
|
364
|
+
...update
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
await this.writeDB.put(updatedDoc);
|
|
369
|
+
logger.debug(`Put doc: ${id}`);
|
|
370
|
+
this.pendingUpdates[id].splice(0, updatesToApply.length);
|
|
371
|
+
if (this.pendingUpdates[id].length === 0) {
|
|
372
|
+
this.inprogressUpdates[id] = false;
|
|
373
|
+
delete this.inprogressUpdates[id];
|
|
358
374
|
} else {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
375
|
+
return this.applyUpdates(id);
|
|
376
|
+
}
|
|
377
|
+
return updatedDoc;
|
|
378
|
+
} catch (e) {
|
|
379
|
+
if (e.name === "conflict" && i < MAX_RETRIES - 1) {
|
|
380
|
+
logger.warn(`Conflict on update for doc ${id}, retry #${i + 1}`);
|
|
381
|
+
await new Promise((res) => setTimeout(res, 50 * Math.random()));
|
|
382
|
+
} else {
|
|
383
|
+
delete this.inprogressUpdates[id];
|
|
384
|
+
if (this.pendingUpdates[id]) {
|
|
385
|
+
delete this.pendingUpdates[id];
|
|
386
|
+
}
|
|
387
|
+
logger.error(`Error on attemped update (retry ${i}): ${JSON.stringify(e)}`);
|
|
388
|
+
throw e;
|
|
363
389
|
}
|
|
364
390
|
}
|
|
365
|
-
await this.writeDB.put(doc);
|
|
366
|
-
logger.debug(`Put doc: ${id}`);
|
|
367
|
-
if (this.pendingUpdates[id].length === 0) {
|
|
368
|
-
this.inprogressUpdates[id] = false;
|
|
369
|
-
delete this.inprogressUpdates[id];
|
|
370
|
-
} else {
|
|
371
|
-
return this.applyUpdates(id);
|
|
372
|
-
}
|
|
373
|
-
return doc;
|
|
374
|
-
} catch (e) {
|
|
375
|
-
delete this.inprogressUpdates[id];
|
|
376
|
-
if (this.pendingUpdates[id]) {
|
|
377
|
-
delete this.pendingUpdates[id];
|
|
378
|
-
}
|
|
379
|
-
logger.error(`Error on attemped update: ${JSON.stringify(e)}`);
|
|
380
|
-
throw e;
|
|
381
391
|
}
|
|
392
|
+
throw new Error(`UpdateQueue failed for doc ${id} after ${MAX_RETRIES} retries.`);
|
|
382
393
|
} else {
|
|
383
394
|
throw new Error(`Empty Updates Queue Triggered`);
|
|
384
395
|
}
|
|
@@ -629,7 +640,7 @@ function getCourseDB(courseID) {
|
|
|
629
640
|
const dbName = `coursedb-${courseID}`;
|
|
630
641
|
return new pouchdb_setup_default(
|
|
631
642
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
632
|
-
|
|
643
|
+
createPouchDBConfig()
|
|
633
644
|
);
|
|
634
645
|
}
|
|
635
646
|
var import_common, import_common2, import_common3, import_uuid, AlreadyTaggedErr;
|
|
@@ -713,13 +724,16 @@ var init_elo = __esm({
|
|
|
713
724
|
}
|
|
714
725
|
async getNewCards(limit = 99) {
|
|
715
726
|
const activeCards = await this.user.getActiveCards();
|
|
716
|
-
return (await this.course.getCardsCenteredAtELO(
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
727
|
+
return (await this.course.getCardsCenteredAtELO(
|
|
728
|
+
{ limit, elo: "user" },
|
|
729
|
+
(c) => {
|
|
730
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
731
|
+
return false;
|
|
732
|
+
} else {
|
|
733
|
+
return true;
|
|
734
|
+
}
|
|
721
735
|
}
|
|
722
|
-
|
|
736
|
+
)).map((c) => {
|
|
723
737
|
return {
|
|
724
738
|
...c,
|
|
725
739
|
status: "new"
|
|
@@ -767,7 +781,7 @@ var init_navigators = __esm({
|
|
|
767
781
|
static async create(user, course, strategyData) {
|
|
768
782
|
const implementingClass = strategyData.implementingClass;
|
|
769
783
|
let NavigatorImpl;
|
|
770
|
-
const variations = ["", ".js", "
|
|
784
|
+
const variations = [".ts", ".js", ""];
|
|
771
785
|
for (const ext of variations) {
|
|
772
786
|
try {
|
|
773
787
|
const module2 = await globImport(`./${implementingClass}${ext}`);
|
|
@@ -1026,7 +1040,13 @@ var init_courseDB = __esm({
|
|
|
1026
1040
|
} else {
|
|
1027
1041
|
return s;
|
|
1028
1042
|
}
|
|
1029
|
-
}).map((c) =>
|
|
1043
|
+
}).map((c) => {
|
|
1044
|
+
return {
|
|
1045
|
+
courseID: this.id,
|
|
1046
|
+
cardID: c.id,
|
|
1047
|
+
elo: c.key
|
|
1048
|
+
};
|
|
1049
|
+
});
|
|
1030
1050
|
const str = `below:
|
|
1031
1051
|
${below.rows.map((r) => ` ${r.id}-${r.key}
|
|
1032
1052
|
`)}
|
|
@@ -1081,7 +1101,13 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1081
1101
|
}
|
|
1082
1102
|
}
|
|
1083
1103
|
async addTagToCard(cardId, tagId, updateELO) {
|
|
1084
|
-
return await addTagToCard(
|
|
1104
|
+
return await addTagToCard(
|
|
1105
|
+
this.id,
|
|
1106
|
+
cardId,
|
|
1107
|
+
tagId,
|
|
1108
|
+
(await this._getCurrentUser()).getUsername(),
|
|
1109
|
+
updateELO
|
|
1110
|
+
);
|
|
1085
1111
|
}
|
|
1086
1112
|
async removeTagFromCard(cardId, tagId) {
|
|
1087
1113
|
return await removeTagFromCard(this.id, cardId, tagId);
|
|
@@ -1274,17 +1300,93 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1274
1300
|
selectedCards.push(card);
|
|
1275
1301
|
}
|
|
1276
1302
|
return selectedCards.map((c) => {
|
|
1277
|
-
const split = c.split("-");
|
|
1278
1303
|
return {
|
|
1279
1304
|
courseID: this.id,
|
|
1280
|
-
cardID:
|
|
1281
|
-
qualifiedID: `${split[0]}-${split[1]}`,
|
|
1305
|
+
cardID: c.cardID,
|
|
1282
1306
|
contentSourceType: "course",
|
|
1283
1307
|
contentSourceID: this.id,
|
|
1308
|
+
elo: c.elo,
|
|
1284
1309
|
status: "new"
|
|
1285
1310
|
};
|
|
1286
1311
|
});
|
|
1287
1312
|
}
|
|
1313
|
+
// Admin search methods
|
|
1314
|
+
async searchCards(query) {
|
|
1315
|
+
logger.log(`[CourseDB ${this.id}] Searching for: "${query}"`);
|
|
1316
|
+
let displayableData;
|
|
1317
|
+
try {
|
|
1318
|
+
displayableData = await this.db.find({
|
|
1319
|
+
selector: {
|
|
1320
|
+
docType: "DISPLAYABLE_DATA",
|
|
1321
|
+
"data.0.data": { $regex: `.*${query}.*` }
|
|
1322
|
+
}
|
|
1323
|
+
});
|
|
1324
|
+
logger.log(`[CourseDB ${this.id}] Regex search on data[0].data successful`);
|
|
1325
|
+
} catch (regexError) {
|
|
1326
|
+
logger.log(
|
|
1327
|
+
`[CourseDB ${this.id}] Regex search failed, falling back to manual search:`,
|
|
1328
|
+
regexError
|
|
1329
|
+
);
|
|
1330
|
+
const allDisplayable = await this.db.find({
|
|
1331
|
+
selector: {
|
|
1332
|
+
docType: "DISPLAYABLE_DATA"
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
logger.log(
|
|
1336
|
+
`[CourseDB ${this.id}] Retrieved ${allDisplayable.docs.length} documents for manual filtering`
|
|
1337
|
+
);
|
|
1338
|
+
displayableData = {
|
|
1339
|
+
docs: allDisplayable.docs.filter((doc) => {
|
|
1340
|
+
const docString = JSON.stringify(doc).toLowerCase();
|
|
1341
|
+
const match = docString.includes(query.toLowerCase());
|
|
1342
|
+
if (match) {
|
|
1343
|
+
logger.log(`[CourseDB ${this.id}] Manual match found in document: ${doc._id}`);
|
|
1344
|
+
}
|
|
1345
|
+
return match;
|
|
1346
|
+
})
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
logger.log(
|
|
1350
|
+
`[CourseDB ${this.id}] Found ${displayableData.docs.length} displayable data documents`
|
|
1351
|
+
);
|
|
1352
|
+
if (displayableData.docs.length === 0) {
|
|
1353
|
+
const allDisplayableData = await this.db.find({
|
|
1354
|
+
selector: {
|
|
1355
|
+
docType: "DISPLAYABLE_DATA"
|
|
1356
|
+
},
|
|
1357
|
+
limit: 5
|
|
1358
|
+
// Just sample a few
|
|
1359
|
+
});
|
|
1360
|
+
logger.log(
|
|
1361
|
+
`[CourseDB ${this.id}] Sample displayable data:`,
|
|
1362
|
+
allDisplayableData.docs.map((d) => ({
|
|
1363
|
+
id: d._id,
|
|
1364
|
+
docType: d.docType,
|
|
1365
|
+
dataStructure: d.data ? Object.keys(d.data) : "no data field",
|
|
1366
|
+
dataContent: d.data,
|
|
1367
|
+
fullDoc: d
|
|
1368
|
+
}))
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
const allResults = [];
|
|
1372
|
+
for (const dd of displayableData.docs) {
|
|
1373
|
+
const cards = await this.db.find({
|
|
1374
|
+
selector: {
|
|
1375
|
+
docType: "CARD",
|
|
1376
|
+
id_displayable_data: { $in: [dd._id] }
|
|
1377
|
+
}
|
|
1378
|
+
});
|
|
1379
|
+
logger.log(
|
|
1380
|
+
`[CourseDB ${this.id}] Displayable data ${dd._id} linked to ${cards.docs.length} cards`
|
|
1381
|
+
);
|
|
1382
|
+
allResults.push(...cards.docs);
|
|
1383
|
+
}
|
|
1384
|
+
logger.log(`[CourseDB ${this.id}] Total cards found: ${allResults.length}`);
|
|
1385
|
+
return allResults;
|
|
1386
|
+
}
|
|
1387
|
+
async find(request) {
|
|
1388
|
+
return this.db.find(request);
|
|
1389
|
+
}
|
|
1288
1390
|
};
|
|
1289
1391
|
}
|
|
1290
1392
|
});
|
|
@@ -1349,7 +1451,7 @@ var init_classroomDB2 = __esm({
|
|
|
1349
1451
|
const dbName = `classdb-student-${this._id}`;
|
|
1350
1452
|
this._db = new pouchdb_setup_default(
|
|
1351
1453
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
1352
|
-
|
|
1454
|
+
createPouchDBConfig()
|
|
1353
1455
|
);
|
|
1354
1456
|
try {
|
|
1355
1457
|
const cfg = await this._db.get(CLASSROOM_CONFIG);
|
|
@@ -1418,9 +1520,11 @@ var init_classroomDB2 = __esm({
|
|
|
1418
1520
|
ret.push(await getCourseDB2(content.courseID).get(content.cardID));
|
|
1419
1521
|
}
|
|
1420
1522
|
}
|
|
1421
|
-
logger.info(
|
|
1523
|
+
logger.info(
|
|
1524
|
+
`New Cards from classroom ${this._cfg.name}: ${ret.map((c) => `${c.courseID}-${c.cardID}`)}`
|
|
1525
|
+
);
|
|
1422
1526
|
return ret.filter((c) => {
|
|
1423
|
-
if (activeCards.some((ac) => c.
|
|
1527
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
1424
1528
|
return false;
|
|
1425
1529
|
} else {
|
|
1426
1530
|
return true;
|
|
@@ -1473,10 +1577,29 @@ var init_CouchDBSyncStrategy = __esm({
|
|
|
1473
1577
|
});
|
|
1474
1578
|
|
|
1475
1579
|
// src/impl/couch/index.ts
|
|
1580
|
+
function createPouchDBConfig() {
|
|
1581
|
+
const hasExplicitCredentials = ENV.COUCHDB_USERNAME && ENV.COUCHDB_PASSWORD;
|
|
1582
|
+
const isNodeEnvironment = typeof window === "undefined";
|
|
1583
|
+
if (hasExplicitCredentials && isNodeEnvironment) {
|
|
1584
|
+
return {
|
|
1585
|
+
fetch(url, opts = {}) {
|
|
1586
|
+
const basicAuth = btoa(`${ENV.COUCHDB_USERNAME}:${ENV.COUCHDB_PASSWORD}`);
|
|
1587
|
+
const headers = new Headers(opts.headers || {});
|
|
1588
|
+
headers.set("Authorization", `Basic ${basicAuth}`);
|
|
1589
|
+
const newOpts = {
|
|
1590
|
+
...opts,
|
|
1591
|
+
headers
|
|
1592
|
+
};
|
|
1593
|
+
return pouchdb_setup_default.fetch(url, newOpts);
|
|
1594
|
+
}
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
return pouchDBincludeCredentialsConfig;
|
|
1598
|
+
}
|
|
1476
1599
|
function getCourseDB2(courseID) {
|
|
1477
1600
|
return new pouchdb_setup_default(
|
|
1478
1601
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + "coursedb-" + courseID,
|
|
1479
|
-
|
|
1602
|
+
createPouchDBConfig()
|
|
1480
1603
|
);
|
|
1481
1604
|
}
|
|
1482
1605
|
function getCourseDocs(courseID, docIDs, options = {}) {
|
|
@@ -1768,6 +1891,9 @@ Currently logged-in as ${this._username}.`
|
|
|
1768
1891
|
await this.init();
|
|
1769
1892
|
return ret;
|
|
1770
1893
|
}
|
|
1894
|
+
async get(id) {
|
|
1895
|
+
return this.localDB.get(id);
|
|
1896
|
+
}
|
|
1771
1897
|
update(id, update) {
|
|
1772
1898
|
return this.updateQueue.update(id, update);
|
|
1773
1899
|
}
|
|
@@ -1814,7 +1940,12 @@ Currently logged-in as ${this._username}.`
|
|
|
1814
1940
|
endkey: keys.endkey,
|
|
1815
1941
|
include_docs: true
|
|
1816
1942
|
});
|
|
1817
|
-
return reviews.rows.map((r) =>
|
|
1943
|
+
return reviews.rows.map((r) => {
|
|
1944
|
+
return {
|
|
1945
|
+
courseID: r.doc.courseId,
|
|
1946
|
+
cardID: r.doc.cardId
|
|
1947
|
+
};
|
|
1948
|
+
});
|
|
1818
1949
|
}
|
|
1819
1950
|
async getActivityRecords() {
|
|
1820
1951
|
try {
|
|
@@ -2094,8 +2225,18 @@ Currently logged-in as ${this._username}.`
|
|
|
2094
2225
|
}
|
|
2095
2226
|
this.setDBandQ();
|
|
2096
2227
|
this.syncStrategy.startSync(this.localDB, this.remoteDB);
|
|
2097
|
-
|
|
2098
|
-
|
|
2228
|
+
this.applyDesignDocs().catch((error) => {
|
|
2229
|
+
log3(`Error in applyDesignDocs background task: ${error}`);
|
|
2230
|
+
if (error && typeof error === "object") {
|
|
2231
|
+
log3(`Full error details in applyDesignDocs: ${JSON.stringify(error)}`);
|
|
2232
|
+
}
|
|
2233
|
+
});
|
|
2234
|
+
this.deduplicateReviews().catch((error) => {
|
|
2235
|
+
log3(`Error in deduplicateReviews background task: ${error}`);
|
|
2236
|
+
if (error && typeof error === "object") {
|
|
2237
|
+
log3(`Full error details in background task: ${JSON.stringify(error)}`);
|
|
2238
|
+
}
|
|
2239
|
+
});
|
|
2099
2240
|
_BaseUser._initialized = true;
|
|
2100
2241
|
}
|
|
2101
2242
|
static designDocs = [
|
|
@@ -2113,10 +2254,15 @@ Currently logged-in as ${this._username}.`
|
|
|
2113
2254
|
}
|
|
2114
2255
|
];
|
|
2115
2256
|
async applyDesignDocs() {
|
|
2257
|
+
log3(`Starting applyDesignDocs for user: ${this._username}`);
|
|
2258
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
2116
2259
|
if (this._username === "admin") {
|
|
2260
|
+
log3("Skipping design docs for admin user");
|
|
2117
2261
|
return;
|
|
2118
2262
|
}
|
|
2263
|
+
log3(`Applying ${_BaseUser.designDocs.length} design docs`);
|
|
2119
2264
|
for (const doc of _BaseUser.designDocs) {
|
|
2265
|
+
log3(`Applying design doc: ${doc._id}`);
|
|
2120
2266
|
try {
|
|
2121
2267
|
try {
|
|
2122
2268
|
const existingDoc = await this.remoteDB.get(doc._id);
|
|
@@ -2215,8 +2361,13 @@ Currently logged-in as ${this._username}.`
|
|
|
2215
2361
|
async deduplicateReviews() {
|
|
2216
2362
|
try {
|
|
2217
2363
|
log3("Starting deduplication of scheduled reviews...");
|
|
2364
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
2365
|
+
log3(`Write DB name: ${this.writeDB.name || "unknown"}`);
|
|
2218
2366
|
const reviewsMap = {};
|
|
2219
2367
|
const duplicateDocIds = [];
|
|
2368
|
+
log3(
|
|
2369
|
+
`Attempting to query remoteDB for reviewCards/reviewCards. Database: ${this.remoteDB.name || "unknown"}`
|
|
2370
|
+
);
|
|
2220
2371
|
const scheduledReviews = await this.remoteDB.query("reviewCards/reviewCards");
|
|
2221
2372
|
log3(`Found ${scheduledReviews.rows.length} scheduled reviews to process`);
|
|
2222
2373
|
scheduledReviews.rows.forEach((r) => {
|
|
@@ -2251,6 +2402,17 @@ Currently logged-in as ${this._username}.`
|
|
|
2251
2402
|
}
|
|
2252
2403
|
} catch (error) {
|
|
2253
2404
|
log3(`Error during review deduplication: ${error}`);
|
|
2405
|
+
if (error && typeof error === "object" && "status" in error && error.status === 404) {
|
|
2406
|
+
log3(
|
|
2407
|
+
`Database not found (404) during review deduplication. Database: ${this.remoteDB.name || "unknown"}`
|
|
2408
|
+
);
|
|
2409
|
+
log3(
|
|
2410
|
+
`This might indicate the user database doesn't exist or the reviewCards view isn't available`
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
if (error && typeof error === "object") {
|
|
2414
|
+
log3(`Full error details: ${JSON.stringify(error)}`);
|
|
2415
|
+
}
|
|
2254
2416
|
}
|
|
2255
2417
|
}
|
|
2256
2418
|
/**
|