@vue-skuilder/db 0.1.11-7 → 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.mjs
CHANGED
|
@@ -165,9 +165,9 @@ var init_pouchdb_setup = __esm({
|
|
|
165
165
|
PouchDB.plugin(PouchDBFind);
|
|
166
166
|
PouchDB.plugin(PouchDBAuth);
|
|
167
167
|
PouchDB.defaults({
|
|
168
|
-
ajax: {
|
|
169
|
-
|
|
170
|
-
}
|
|
168
|
+
// ajax: {
|
|
169
|
+
// timeout: 60000,
|
|
170
|
+
// },
|
|
171
171
|
});
|
|
172
172
|
pouchdb_setup_default = PouchDB;
|
|
173
173
|
}
|
|
@@ -325,37 +325,48 @@ var init_updateQueue = __esm({
|
|
|
325
325
|
} else {
|
|
326
326
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
327
327
|
this.inprogressUpdates[id] = true;
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
328
|
+
const MAX_RETRIES = 5;
|
|
329
|
+
for (let i = 0; i < MAX_RETRIES; i++) {
|
|
330
|
+
try {
|
|
331
|
+
const doc = await this.readDB.get(id);
|
|
332
|
+
logger.debug(`Retrieved doc: ${id}`);
|
|
333
|
+
let updatedDoc = { ...doc };
|
|
334
|
+
const updatesToApply = [...this.pendingUpdates[id]];
|
|
335
|
+
for (const update of updatesToApply) {
|
|
336
|
+
if (typeof update === "function") {
|
|
337
|
+
updatedDoc = { ...updatedDoc, ...update(updatedDoc) };
|
|
338
|
+
} else {
|
|
339
|
+
updatedDoc = {
|
|
340
|
+
...updatedDoc,
|
|
341
|
+
...update
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
await this.writeDB.put(updatedDoc);
|
|
346
|
+
logger.debug(`Put doc: ${id}`);
|
|
347
|
+
this.pendingUpdates[id].splice(0, updatesToApply.length);
|
|
348
|
+
if (this.pendingUpdates[id].length === 0) {
|
|
349
|
+
this.inprogressUpdates[id] = false;
|
|
350
|
+
delete this.inprogressUpdates[id];
|
|
335
351
|
} else {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
352
|
+
return this.applyUpdates(id);
|
|
353
|
+
}
|
|
354
|
+
return updatedDoc;
|
|
355
|
+
} catch (e) {
|
|
356
|
+
if (e.name === "conflict" && i < MAX_RETRIES - 1) {
|
|
357
|
+
logger.warn(`Conflict on update for doc ${id}, retry #${i + 1}`);
|
|
358
|
+
await new Promise((res) => setTimeout(res, 50 * Math.random()));
|
|
359
|
+
} else {
|
|
360
|
+
delete this.inprogressUpdates[id];
|
|
361
|
+
if (this.pendingUpdates[id]) {
|
|
362
|
+
delete this.pendingUpdates[id];
|
|
363
|
+
}
|
|
364
|
+
logger.error(`Error on attemped update (retry ${i}): ${JSON.stringify(e)}`);
|
|
365
|
+
throw e;
|
|
340
366
|
}
|
|
341
367
|
}
|
|
342
|
-
await this.writeDB.put(doc);
|
|
343
|
-
logger.debug(`Put doc: ${id}`);
|
|
344
|
-
if (this.pendingUpdates[id].length === 0) {
|
|
345
|
-
this.inprogressUpdates[id] = false;
|
|
346
|
-
delete this.inprogressUpdates[id];
|
|
347
|
-
} else {
|
|
348
|
-
return this.applyUpdates(id);
|
|
349
|
-
}
|
|
350
|
-
return doc;
|
|
351
|
-
} catch (e) {
|
|
352
|
-
delete this.inprogressUpdates[id];
|
|
353
|
-
if (this.pendingUpdates[id]) {
|
|
354
|
-
delete this.pendingUpdates[id];
|
|
355
|
-
}
|
|
356
|
-
logger.error(`Error on attemped update: ${JSON.stringify(e)}`);
|
|
357
|
-
throw e;
|
|
358
368
|
}
|
|
369
|
+
throw new Error(`UpdateQueue failed for doc ${id} after ${MAX_RETRIES} retries.`);
|
|
359
370
|
} else {
|
|
360
371
|
throw new Error(`Empty Updates Queue Triggered`);
|
|
361
372
|
}
|
|
@@ -610,7 +621,7 @@ function getCourseDB(courseID) {
|
|
|
610
621
|
const dbName = `coursedb-${courseID}`;
|
|
611
622
|
return new pouchdb_setup_default(
|
|
612
623
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
613
|
-
|
|
624
|
+
createPouchDBConfig()
|
|
614
625
|
);
|
|
615
626
|
}
|
|
616
627
|
var AlreadyTaggedErr;
|
|
@@ -690,13 +701,16 @@ var init_elo = __esm({
|
|
|
690
701
|
}
|
|
691
702
|
async getNewCards(limit = 99) {
|
|
692
703
|
const activeCards = await this.user.getActiveCards();
|
|
693
|
-
return (await this.course.getCardsCenteredAtELO(
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
704
|
+
return (await this.course.getCardsCenteredAtELO(
|
|
705
|
+
{ limit, elo: "user" },
|
|
706
|
+
(c) => {
|
|
707
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
708
|
+
return false;
|
|
709
|
+
} else {
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
698
712
|
}
|
|
699
|
-
|
|
713
|
+
)).map((c) => {
|
|
700
714
|
return {
|
|
701
715
|
...c,
|
|
702
716
|
status: "new"
|
|
@@ -744,7 +758,7 @@ var init_navigators = __esm({
|
|
|
744
758
|
static async create(user, course, strategyData) {
|
|
745
759
|
const implementingClass = strategyData.implementingClass;
|
|
746
760
|
let NavigatorImpl;
|
|
747
|
-
const variations = ["", ".js", "
|
|
761
|
+
const variations = [".ts", ".js", ""];
|
|
748
762
|
for (const ext of variations) {
|
|
749
763
|
try {
|
|
750
764
|
const module = await globImport(`./${implementingClass}${ext}`);
|
|
@@ -1008,7 +1022,13 @@ var init_courseDB = __esm({
|
|
|
1008
1022
|
} else {
|
|
1009
1023
|
return s;
|
|
1010
1024
|
}
|
|
1011
|
-
}).map((c) =>
|
|
1025
|
+
}).map((c) => {
|
|
1026
|
+
return {
|
|
1027
|
+
courseID: this.id,
|
|
1028
|
+
cardID: c.id,
|
|
1029
|
+
elo: c.key
|
|
1030
|
+
};
|
|
1031
|
+
});
|
|
1012
1032
|
const str = `below:
|
|
1013
1033
|
${below.rows.map((r) => ` ${r.id}-${r.key}
|
|
1014
1034
|
`)}
|
|
@@ -1063,7 +1083,13 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1063
1083
|
}
|
|
1064
1084
|
}
|
|
1065
1085
|
async addTagToCard(cardId, tagId, updateELO) {
|
|
1066
|
-
return await addTagToCard(
|
|
1086
|
+
return await addTagToCard(
|
|
1087
|
+
this.id,
|
|
1088
|
+
cardId,
|
|
1089
|
+
tagId,
|
|
1090
|
+
(await this._getCurrentUser()).getUsername(),
|
|
1091
|
+
updateELO
|
|
1092
|
+
);
|
|
1067
1093
|
}
|
|
1068
1094
|
async removeTagFromCard(cardId, tagId) {
|
|
1069
1095
|
return await removeTagFromCard(this.id, cardId, tagId);
|
|
@@ -1256,17 +1282,93 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1256
1282
|
selectedCards.push(card);
|
|
1257
1283
|
}
|
|
1258
1284
|
return selectedCards.map((c) => {
|
|
1259
|
-
const split = c.split("-");
|
|
1260
1285
|
return {
|
|
1261
1286
|
courseID: this.id,
|
|
1262
|
-
cardID:
|
|
1263
|
-
qualifiedID: `${split[0]}-${split[1]}`,
|
|
1287
|
+
cardID: c.cardID,
|
|
1264
1288
|
contentSourceType: "course",
|
|
1265
1289
|
contentSourceID: this.id,
|
|
1290
|
+
elo: c.elo,
|
|
1266
1291
|
status: "new"
|
|
1267
1292
|
};
|
|
1268
1293
|
});
|
|
1269
1294
|
}
|
|
1295
|
+
// Admin search methods
|
|
1296
|
+
async searchCards(query) {
|
|
1297
|
+
logger.log(`[CourseDB ${this.id}] Searching for: "${query}"`);
|
|
1298
|
+
let displayableData;
|
|
1299
|
+
try {
|
|
1300
|
+
displayableData = await this.db.find({
|
|
1301
|
+
selector: {
|
|
1302
|
+
docType: "DISPLAYABLE_DATA",
|
|
1303
|
+
"data.0.data": { $regex: `.*${query}.*` }
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
logger.log(`[CourseDB ${this.id}] Regex search on data[0].data successful`);
|
|
1307
|
+
} catch (regexError) {
|
|
1308
|
+
logger.log(
|
|
1309
|
+
`[CourseDB ${this.id}] Regex search failed, falling back to manual search:`,
|
|
1310
|
+
regexError
|
|
1311
|
+
);
|
|
1312
|
+
const allDisplayable = await this.db.find({
|
|
1313
|
+
selector: {
|
|
1314
|
+
docType: "DISPLAYABLE_DATA"
|
|
1315
|
+
}
|
|
1316
|
+
});
|
|
1317
|
+
logger.log(
|
|
1318
|
+
`[CourseDB ${this.id}] Retrieved ${allDisplayable.docs.length} documents for manual filtering`
|
|
1319
|
+
);
|
|
1320
|
+
displayableData = {
|
|
1321
|
+
docs: allDisplayable.docs.filter((doc) => {
|
|
1322
|
+
const docString = JSON.stringify(doc).toLowerCase();
|
|
1323
|
+
const match = docString.includes(query.toLowerCase());
|
|
1324
|
+
if (match) {
|
|
1325
|
+
logger.log(`[CourseDB ${this.id}] Manual match found in document: ${doc._id}`);
|
|
1326
|
+
}
|
|
1327
|
+
return match;
|
|
1328
|
+
})
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
logger.log(
|
|
1332
|
+
`[CourseDB ${this.id}] Found ${displayableData.docs.length} displayable data documents`
|
|
1333
|
+
);
|
|
1334
|
+
if (displayableData.docs.length === 0) {
|
|
1335
|
+
const allDisplayableData = await this.db.find({
|
|
1336
|
+
selector: {
|
|
1337
|
+
docType: "DISPLAYABLE_DATA"
|
|
1338
|
+
},
|
|
1339
|
+
limit: 5
|
|
1340
|
+
// Just sample a few
|
|
1341
|
+
});
|
|
1342
|
+
logger.log(
|
|
1343
|
+
`[CourseDB ${this.id}] Sample displayable data:`,
|
|
1344
|
+
allDisplayableData.docs.map((d) => ({
|
|
1345
|
+
id: d._id,
|
|
1346
|
+
docType: d.docType,
|
|
1347
|
+
dataStructure: d.data ? Object.keys(d.data) : "no data field",
|
|
1348
|
+
dataContent: d.data,
|
|
1349
|
+
fullDoc: d
|
|
1350
|
+
}))
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
const allResults = [];
|
|
1354
|
+
for (const dd of displayableData.docs) {
|
|
1355
|
+
const cards = await this.db.find({
|
|
1356
|
+
selector: {
|
|
1357
|
+
docType: "CARD",
|
|
1358
|
+
id_displayable_data: { $in: [dd._id] }
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1361
|
+
logger.log(
|
|
1362
|
+
`[CourseDB ${this.id}] Displayable data ${dd._id} linked to ${cards.docs.length} cards`
|
|
1363
|
+
);
|
|
1364
|
+
allResults.push(...cards.docs);
|
|
1365
|
+
}
|
|
1366
|
+
logger.log(`[CourseDB ${this.id}] Total cards found: ${allResults.length}`);
|
|
1367
|
+
return allResults;
|
|
1368
|
+
}
|
|
1369
|
+
async find(request) {
|
|
1370
|
+
return this.db.find(request);
|
|
1371
|
+
}
|
|
1270
1372
|
};
|
|
1271
1373
|
}
|
|
1272
1374
|
});
|
|
@@ -1331,7 +1433,7 @@ var init_classroomDB2 = __esm({
|
|
|
1331
1433
|
const dbName = `classdb-student-${this._id}`;
|
|
1332
1434
|
this._db = new pouchdb_setup_default(
|
|
1333
1435
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
1334
|
-
|
|
1436
|
+
createPouchDBConfig()
|
|
1335
1437
|
);
|
|
1336
1438
|
try {
|
|
1337
1439
|
const cfg = await this._db.get(CLASSROOM_CONFIG);
|
|
@@ -1400,9 +1502,11 @@ var init_classroomDB2 = __esm({
|
|
|
1400
1502
|
ret.push(await getCourseDB2(content.courseID).get(content.cardID));
|
|
1401
1503
|
}
|
|
1402
1504
|
}
|
|
1403
|
-
logger.info(
|
|
1505
|
+
logger.info(
|
|
1506
|
+
`New Cards from classroom ${this._cfg.name}: ${ret.map((c) => `${c.courseID}-${c.cardID}`)}`
|
|
1507
|
+
);
|
|
1404
1508
|
return ret.filter((c) => {
|
|
1405
|
-
if (activeCards.some((ac) => c.
|
|
1509
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
1406
1510
|
return false;
|
|
1407
1511
|
} else {
|
|
1408
1512
|
return true;
|
|
@@ -1456,10 +1560,29 @@ var init_CouchDBSyncStrategy = __esm({
|
|
|
1456
1560
|
import fetch2 from "cross-fetch";
|
|
1457
1561
|
import moment4 from "moment";
|
|
1458
1562
|
import process2 from "process";
|
|
1563
|
+
function createPouchDBConfig() {
|
|
1564
|
+
const hasExplicitCredentials = ENV.COUCHDB_USERNAME && ENV.COUCHDB_PASSWORD;
|
|
1565
|
+
const isNodeEnvironment = typeof window === "undefined";
|
|
1566
|
+
if (hasExplicitCredentials && isNodeEnvironment) {
|
|
1567
|
+
return {
|
|
1568
|
+
fetch(url, opts = {}) {
|
|
1569
|
+
const basicAuth = btoa(`${ENV.COUCHDB_USERNAME}:${ENV.COUCHDB_PASSWORD}`);
|
|
1570
|
+
const headers = new Headers(opts.headers || {});
|
|
1571
|
+
headers.set("Authorization", `Basic ${basicAuth}`);
|
|
1572
|
+
const newOpts = {
|
|
1573
|
+
...opts,
|
|
1574
|
+
headers
|
|
1575
|
+
};
|
|
1576
|
+
return pouchdb_setup_default.fetch(url, newOpts);
|
|
1577
|
+
}
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
return pouchDBincludeCredentialsConfig;
|
|
1581
|
+
}
|
|
1459
1582
|
function getCourseDB2(courseID) {
|
|
1460
1583
|
return new pouchdb_setup_default(
|
|
1461
1584
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + "coursedb-" + courseID,
|
|
1462
|
-
|
|
1585
|
+
createPouchDBConfig()
|
|
1463
1586
|
);
|
|
1464
1587
|
}
|
|
1465
1588
|
function getCourseDocs(courseID, docIDs, options = {}) {
|
|
@@ -1748,6 +1871,9 @@ Currently logged-in as ${this._username}.`
|
|
|
1748
1871
|
await this.init();
|
|
1749
1872
|
return ret;
|
|
1750
1873
|
}
|
|
1874
|
+
async get(id) {
|
|
1875
|
+
return this.localDB.get(id);
|
|
1876
|
+
}
|
|
1751
1877
|
update(id, update) {
|
|
1752
1878
|
return this.updateQueue.update(id, update);
|
|
1753
1879
|
}
|
|
@@ -1794,7 +1920,12 @@ Currently logged-in as ${this._username}.`
|
|
|
1794
1920
|
endkey: keys.endkey,
|
|
1795
1921
|
include_docs: true
|
|
1796
1922
|
});
|
|
1797
|
-
return reviews.rows.map((r) =>
|
|
1923
|
+
return reviews.rows.map((r) => {
|
|
1924
|
+
return {
|
|
1925
|
+
courseID: r.doc.courseId,
|
|
1926
|
+
cardID: r.doc.cardId
|
|
1927
|
+
};
|
|
1928
|
+
});
|
|
1798
1929
|
}
|
|
1799
1930
|
async getActivityRecords() {
|
|
1800
1931
|
try {
|
|
@@ -2074,8 +2205,18 @@ Currently logged-in as ${this._username}.`
|
|
|
2074
2205
|
}
|
|
2075
2206
|
this.setDBandQ();
|
|
2076
2207
|
this.syncStrategy.startSync(this.localDB, this.remoteDB);
|
|
2077
|
-
|
|
2078
|
-
|
|
2208
|
+
this.applyDesignDocs().catch((error) => {
|
|
2209
|
+
log3(`Error in applyDesignDocs background task: ${error}`);
|
|
2210
|
+
if (error && typeof error === "object") {
|
|
2211
|
+
log3(`Full error details in applyDesignDocs: ${JSON.stringify(error)}`);
|
|
2212
|
+
}
|
|
2213
|
+
});
|
|
2214
|
+
this.deduplicateReviews().catch((error) => {
|
|
2215
|
+
log3(`Error in deduplicateReviews background task: ${error}`);
|
|
2216
|
+
if (error && typeof error === "object") {
|
|
2217
|
+
log3(`Full error details in background task: ${JSON.stringify(error)}`);
|
|
2218
|
+
}
|
|
2219
|
+
});
|
|
2079
2220
|
_BaseUser._initialized = true;
|
|
2080
2221
|
}
|
|
2081
2222
|
static designDocs = [
|
|
@@ -2093,10 +2234,15 @@ Currently logged-in as ${this._username}.`
|
|
|
2093
2234
|
}
|
|
2094
2235
|
];
|
|
2095
2236
|
async applyDesignDocs() {
|
|
2237
|
+
log3(`Starting applyDesignDocs for user: ${this._username}`);
|
|
2238
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
2096
2239
|
if (this._username === "admin") {
|
|
2240
|
+
log3("Skipping design docs for admin user");
|
|
2097
2241
|
return;
|
|
2098
2242
|
}
|
|
2243
|
+
log3(`Applying ${_BaseUser.designDocs.length} design docs`);
|
|
2099
2244
|
for (const doc of _BaseUser.designDocs) {
|
|
2245
|
+
log3(`Applying design doc: ${doc._id}`);
|
|
2100
2246
|
try {
|
|
2101
2247
|
try {
|
|
2102
2248
|
const existingDoc = await this.remoteDB.get(doc._id);
|
|
@@ -2195,8 +2341,13 @@ Currently logged-in as ${this._username}.`
|
|
|
2195
2341
|
async deduplicateReviews() {
|
|
2196
2342
|
try {
|
|
2197
2343
|
log3("Starting deduplication of scheduled reviews...");
|
|
2344
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
2345
|
+
log3(`Write DB name: ${this.writeDB.name || "unknown"}`);
|
|
2198
2346
|
const reviewsMap = {};
|
|
2199
2347
|
const duplicateDocIds = [];
|
|
2348
|
+
log3(
|
|
2349
|
+
`Attempting to query remoteDB for reviewCards/reviewCards. Database: ${this.remoteDB.name || "unknown"}`
|
|
2350
|
+
);
|
|
2200
2351
|
const scheduledReviews = await this.remoteDB.query("reviewCards/reviewCards");
|
|
2201
2352
|
log3(`Found ${scheduledReviews.rows.length} scheduled reviews to process`);
|
|
2202
2353
|
scheduledReviews.rows.forEach((r) => {
|
|
@@ -2231,6 +2382,17 @@ Currently logged-in as ${this._username}.`
|
|
|
2231
2382
|
}
|
|
2232
2383
|
} catch (error) {
|
|
2233
2384
|
log3(`Error during review deduplication: ${error}`);
|
|
2385
|
+
if (error && typeof error === "object" && "status" in error && error.status === 404) {
|
|
2386
|
+
log3(
|
|
2387
|
+
`Database not found (404) during review deduplication. Database: ${this.remoteDB.name || "unknown"}`
|
|
2388
|
+
);
|
|
2389
|
+
log3(
|
|
2390
|
+
`This might indicate the user database doesn't exist or the reviewCards view isn't available`
|
|
2391
|
+
);
|
|
2392
|
+
}
|
|
2393
|
+
if (error && typeof error === "object") {
|
|
2394
|
+
log3(`Full error details: ${JSON.stringify(error)}`);
|
|
2395
|
+
}
|
|
2234
2396
|
}
|
|
2235
2397
|
}
|
|
2236
2398
|
/**
|