@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
|
@@ -90,9 +90,9 @@ var init_pouchdb_setup = __esm({
|
|
|
90
90
|
PouchDB.plugin(PouchDBFind);
|
|
91
91
|
PouchDB.plugin(PouchDBAuth);
|
|
92
92
|
PouchDB.defaults({
|
|
93
|
-
ajax: {
|
|
94
|
-
|
|
95
|
-
}
|
|
93
|
+
// ajax: {
|
|
94
|
+
// timeout: 60000,
|
|
95
|
+
// },
|
|
96
96
|
});
|
|
97
97
|
pouchdb_setup_default = PouchDB;
|
|
98
98
|
}
|
|
@@ -155,37 +155,48 @@ var init_updateQueue = __esm({
|
|
|
155
155
|
} else {
|
|
156
156
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
157
157
|
this.inprogressUpdates[id] = true;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
158
|
+
const MAX_RETRIES = 5;
|
|
159
|
+
for (let i = 0; i < MAX_RETRIES; i++) {
|
|
160
|
+
try {
|
|
161
|
+
const doc = await this.readDB.get(id);
|
|
162
|
+
logger.debug(`Retrieved doc: ${id}`);
|
|
163
|
+
let updatedDoc = { ...doc };
|
|
164
|
+
const updatesToApply = [...this.pendingUpdates[id]];
|
|
165
|
+
for (const update of updatesToApply) {
|
|
166
|
+
if (typeof update === "function") {
|
|
167
|
+
updatedDoc = { ...updatedDoc, ...update(updatedDoc) };
|
|
168
|
+
} else {
|
|
169
|
+
updatedDoc = {
|
|
170
|
+
...updatedDoc,
|
|
171
|
+
...update
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
await this.writeDB.put(updatedDoc);
|
|
176
|
+
logger.debug(`Put doc: ${id}`);
|
|
177
|
+
this.pendingUpdates[id].splice(0, updatesToApply.length);
|
|
178
|
+
if (this.pendingUpdates[id].length === 0) {
|
|
179
|
+
this.inprogressUpdates[id] = false;
|
|
180
|
+
delete this.inprogressUpdates[id];
|
|
165
181
|
} else {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
return this.applyUpdates(id);
|
|
183
|
+
}
|
|
184
|
+
return updatedDoc;
|
|
185
|
+
} catch (e) {
|
|
186
|
+
if (e.name === "conflict" && i < MAX_RETRIES - 1) {
|
|
187
|
+
logger.warn(`Conflict on update for doc ${id}, retry #${i + 1}`);
|
|
188
|
+
await new Promise((res) => setTimeout(res, 50 * Math.random()));
|
|
189
|
+
} else {
|
|
190
|
+
delete this.inprogressUpdates[id];
|
|
191
|
+
if (this.pendingUpdates[id]) {
|
|
192
|
+
delete this.pendingUpdates[id];
|
|
193
|
+
}
|
|
194
|
+
logger.error(`Error on attemped update (retry ${i}): ${JSON.stringify(e)}`);
|
|
195
|
+
throw e;
|
|
170
196
|
}
|
|
171
197
|
}
|
|
172
|
-
await this.writeDB.put(doc);
|
|
173
|
-
logger.debug(`Put doc: ${id}`);
|
|
174
|
-
if (this.pendingUpdates[id].length === 0) {
|
|
175
|
-
this.inprogressUpdates[id] = false;
|
|
176
|
-
delete this.inprogressUpdates[id];
|
|
177
|
-
} else {
|
|
178
|
-
return this.applyUpdates(id);
|
|
179
|
-
}
|
|
180
|
-
return doc;
|
|
181
|
-
} catch (e) {
|
|
182
|
-
delete this.inprogressUpdates[id];
|
|
183
|
-
if (this.pendingUpdates[id]) {
|
|
184
|
-
delete this.pendingUpdates[id];
|
|
185
|
-
}
|
|
186
|
-
logger.error(`Error on attemped update: ${JSON.stringify(e)}`);
|
|
187
|
-
throw e;
|
|
188
198
|
}
|
|
199
|
+
throw new Error(`UpdateQueue failed for doc ${id} after ${MAX_RETRIES} retries.`);
|
|
189
200
|
} else {
|
|
190
201
|
throw new Error(`Empty Updates Queue Triggered`);
|
|
191
202
|
}
|
|
@@ -412,7 +423,7 @@ function getCourseDB(courseID) {
|
|
|
412
423
|
const dbName = `coursedb-${courseID}`;
|
|
413
424
|
return new pouchdb_setup_default(
|
|
414
425
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
415
|
-
|
|
426
|
+
createPouchDBConfig()
|
|
416
427
|
);
|
|
417
428
|
}
|
|
418
429
|
var AlreadyTaggedErr;
|
|
@@ -534,6 +545,7 @@ var init_courseLookupDB = __esm({
|
|
|
534
545
|
const doc = await _CourseLookup._db.get(courseID);
|
|
535
546
|
return await _CourseLookup._db.remove(doc);
|
|
536
547
|
}
|
|
548
|
+
// [ ] rename to allCourses()
|
|
537
549
|
static async allCourseWare() {
|
|
538
550
|
const resp = await _CourseLookup._db.allDocs({
|
|
539
551
|
include_docs: true
|
|
@@ -604,13 +616,16 @@ var init_elo = __esm({
|
|
|
604
616
|
}
|
|
605
617
|
async getNewCards(limit = 99) {
|
|
606
618
|
const activeCards = await this.user.getActiveCards();
|
|
607
|
-
return (await this.course.getCardsCenteredAtELO(
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
619
|
+
return (await this.course.getCardsCenteredAtELO(
|
|
620
|
+
{ limit, elo: "user" },
|
|
621
|
+
(c) => {
|
|
622
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
623
|
+
return false;
|
|
624
|
+
} else {
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
612
627
|
}
|
|
613
|
-
|
|
628
|
+
)).map((c) => {
|
|
614
629
|
return {
|
|
615
630
|
...c,
|
|
616
631
|
status: "new"
|
|
@@ -658,7 +673,7 @@ var init_navigators = __esm({
|
|
|
658
673
|
static async create(user, course, strategyData) {
|
|
659
674
|
const implementingClass = strategyData.implementingClass;
|
|
660
675
|
let NavigatorImpl;
|
|
661
|
-
const variations = ["", ".js", "
|
|
676
|
+
const variations = [".ts", ".js", ""];
|
|
662
677
|
for (const ext of variations) {
|
|
663
678
|
try {
|
|
664
679
|
const module = await globImport(`./${implementingClass}${ext}`);
|
|
@@ -1009,7 +1024,13 @@ var init_courseDB = __esm({
|
|
|
1009
1024
|
} else {
|
|
1010
1025
|
return s;
|
|
1011
1026
|
}
|
|
1012
|
-
}).map((c) =>
|
|
1027
|
+
}).map((c) => {
|
|
1028
|
+
return {
|
|
1029
|
+
courseID: this.id,
|
|
1030
|
+
cardID: c.id,
|
|
1031
|
+
elo: c.key
|
|
1032
|
+
};
|
|
1033
|
+
});
|
|
1013
1034
|
const str = `below:
|
|
1014
1035
|
${below.rows.map((r) => ` ${r.id}-${r.key}
|
|
1015
1036
|
`)}
|
|
@@ -1064,7 +1085,13 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1064
1085
|
}
|
|
1065
1086
|
}
|
|
1066
1087
|
async addTagToCard(cardId, tagId, updateELO) {
|
|
1067
|
-
return await addTagToCard(
|
|
1088
|
+
return await addTagToCard(
|
|
1089
|
+
this.id,
|
|
1090
|
+
cardId,
|
|
1091
|
+
tagId,
|
|
1092
|
+
(await this._getCurrentUser()).getUsername(),
|
|
1093
|
+
updateELO
|
|
1094
|
+
);
|
|
1068
1095
|
}
|
|
1069
1096
|
async removeTagFromCard(cardId, tagId) {
|
|
1070
1097
|
return await removeTagFromCard(this.id, cardId, tagId);
|
|
@@ -1257,17 +1284,93 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1257
1284
|
selectedCards.push(card);
|
|
1258
1285
|
}
|
|
1259
1286
|
return selectedCards.map((c) => {
|
|
1260
|
-
const split = c.split("-");
|
|
1261
1287
|
return {
|
|
1262
1288
|
courseID: this.id,
|
|
1263
|
-
cardID:
|
|
1264
|
-
qualifiedID: `${split[0]}-${split[1]}`,
|
|
1289
|
+
cardID: c.cardID,
|
|
1265
1290
|
contentSourceType: "course",
|
|
1266
1291
|
contentSourceID: this.id,
|
|
1292
|
+
elo: c.elo,
|
|
1267
1293
|
status: "new"
|
|
1268
1294
|
};
|
|
1269
1295
|
});
|
|
1270
1296
|
}
|
|
1297
|
+
// Admin search methods
|
|
1298
|
+
async searchCards(query) {
|
|
1299
|
+
logger.log(`[CourseDB ${this.id}] Searching for: "${query}"`);
|
|
1300
|
+
let displayableData;
|
|
1301
|
+
try {
|
|
1302
|
+
displayableData = await this.db.find({
|
|
1303
|
+
selector: {
|
|
1304
|
+
docType: "DISPLAYABLE_DATA",
|
|
1305
|
+
"data.0.data": { $regex: `.*${query}.*` }
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
logger.log(`[CourseDB ${this.id}] Regex search on data[0].data successful`);
|
|
1309
|
+
} catch (regexError) {
|
|
1310
|
+
logger.log(
|
|
1311
|
+
`[CourseDB ${this.id}] Regex search failed, falling back to manual search:`,
|
|
1312
|
+
regexError
|
|
1313
|
+
);
|
|
1314
|
+
const allDisplayable = await this.db.find({
|
|
1315
|
+
selector: {
|
|
1316
|
+
docType: "DISPLAYABLE_DATA"
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
logger.log(
|
|
1320
|
+
`[CourseDB ${this.id}] Retrieved ${allDisplayable.docs.length} documents for manual filtering`
|
|
1321
|
+
);
|
|
1322
|
+
displayableData = {
|
|
1323
|
+
docs: allDisplayable.docs.filter((doc) => {
|
|
1324
|
+
const docString = JSON.stringify(doc).toLowerCase();
|
|
1325
|
+
const match = docString.includes(query.toLowerCase());
|
|
1326
|
+
if (match) {
|
|
1327
|
+
logger.log(`[CourseDB ${this.id}] Manual match found in document: ${doc._id}`);
|
|
1328
|
+
}
|
|
1329
|
+
return match;
|
|
1330
|
+
})
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
logger.log(
|
|
1334
|
+
`[CourseDB ${this.id}] Found ${displayableData.docs.length} displayable data documents`
|
|
1335
|
+
);
|
|
1336
|
+
if (displayableData.docs.length === 0) {
|
|
1337
|
+
const allDisplayableData = await this.db.find({
|
|
1338
|
+
selector: {
|
|
1339
|
+
docType: "DISPLAYABLE_DATA"
|
|
1340
|
+
},
|
|
1341
|
+
limit: 5
|
|
1342
|
+
// Just sample a few
|
|
1343
|
+
});
|
|
1344
|
+
logger.log(
|
|
1345
|
+
`[CourseDB ${this.id}] Sample displayable data:`,
|
|
1346
|
+
allDisplayableData.docs.map((d) => ({
|
|
1347
|
+
id: d._id,
|
|
1348
|
+
docType: d.docType,
|
|
1349
|
+
dataStructure: d.data ? Object.keys(d.data) : "no data field",
|
|
1350
|
+
dataContent: d.data,
|
|
1351
|
+
fullDoc: d
|
|
1352
|
+
}))
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
const allResults = [];
|
|
1356
|
+
for (const dd of displayableData.docs) {
|
|
1357
|
+
const cards = await this.db.find({
|
|
1358
|
+
selector: {
|
|
1359
|
+
docType: "CARD",
|
|
1360
|
+
id_displayable_data: { $in: [dd._id] }
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1363
|
+
logger.log(
|
|
1364
|
+
`[CourseDB ${this.id}] Displayable data ${dd._id} linked to ${cards.docs.length} cards`
|
|
1365
|
+
);
|
|
1366
|
+
allResults.push(...cards.docs);
|
|
1367
|
+
}
|
|
1368
|
+
logger.log(`[CourseDB ${this.id}] Total cards found: ${allResults.length}`);
|
|
1369
|
+
return allResults;
|
|
1370
|
+
}
|
|
1371
|
+
async find(request) {
|
|
1372
|
+
return this.db.find(request);
|
|
1373
|
+
}
|
|
1271
1374
|
};
|
|
1272
1375
|
}
|
|
1273
1376
|
});
|
|
@@ -1279,7 +1382,7 @@ function getClassroomDB(classID, version) {
|
|
|
1279
1382
|
logger.info(`Retrieving classroom db: ${dbName}`);
|
|
1280
1383
|
return new pouchdb_setup_default(
|
|
1281
1384
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
1282
|
-
|
|
1385
|
+
createPouchDBConfig()
|
|
1283
1386
|
);
|
|
1284
1387
|
}
|
|
1285
1388
|
async function getClassroomConfig(classID) {
|
|
@@ -1344,7 +1447,7 @@ var init_classroomDB2 = __esm({
|
|
|
1344
1447
|
const dbName = `classdb-student-${this._id}`;
|
|
1345
1448
|
this._db = new pouchdb_setup_default(
|
|
1346
1449
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
1347
|
-
|
|
1450
|
+
createPouchDBConfig()
|
|
1348
1451
|
);
|
|
1349
1452
|
try {
|
|
1350
1453
|
const cfg = await this._db.get(CLASSROOM_CONFIG);
|
|
@@ -1413,9 +1516,11 @@ var init_classroomDB2 = __esm({
|
|
|
1413
1516
|
ret.push(await getCourseDB2(content.courseID).get(content.cardID));
|
|
1414
1517
|
}
|
|
1415
1518
|
}
|
|
1416
|
-
logger.info(
|
|
1519
|
+
logger.info(
|
|
1520
|
+
`New Cards from classroom ${this._cfg.name}: ${ret.map((c) => `${c.courseID}-${c.cardID}`)}`
|
|
1521
|
+
);
|
|
1417
1522
|
return ret.filter((c) => {
|
|
1418
|
-
if (activeCards.some((ac) => c.
|
|
1523
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
1419
1524
|
return false;
|
|
1420
1525
|
} else {
|
|
1421
1526
|
return true;
|
|
@@ -1434,11 +1539,11 @@ var init_classroomDB2 = __esm({
|
|
|
1434
1539
|
const stuDbName = `classdb-student-${this._id}`;
|
|
1435
1540
|
this._db = new pouchdb_setup_default(
|
|
1436
1541
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
1437
|
-
|
|
1542
|
+
createPouchDBConfig()
|
|
1438
1543
|
);
|
|
1439
1544
|
this._stuDb = new pouchdb_setup_default(
|
|
1440
1545
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + stuDbName,
|
|
1441
|
-
|
|
1546
|
+
createPouchDBConfig()
|
|
1442
1547
|
);
|
|
1443
1548
|
try {
|
|
1444
1549
|
return this._db.get(CLASSROOM_CONFIG).then((cfg) => {
|
|
@@ -2023,6 +2128,9 @@ Currently logged-in as ${this._username}.`
|
|
|
2023
2128
|
await this.init();
|
|
2024
2129
|
return ret;
|
|
2025
2130
|
}
|
|
2131
|
+
async get(id) {
|
|
2132
|
+
return this.localDB.get(id);
|
|
2133
|
+
}
|
|
2026
2134
|
update(id, update) {
|
|
2027
2135
|
return this.updateQueue.update(id, update);
|
|
2028
2136
|
}
|
|
@@ -2069,7 +2177,12 @@ Currently logged-in as ${this._username}.`
|
|
|
2069
2177
|
endkey: keys.endkey,
|
|
2070
2178
|
include_docs: true
|
|
2071
2179
|
});
|
|
2072
|
-
return reviews.rows.map((r) =>
|
|
2180
|
+
return reviews.rows.map((r) => {
|
|
2181
|
+
return {
|
|
2182
|
+
courseID: r.doc.courseId,
|
|
2183
|
+
cardID: r.doc.cardId
|
|
2184
|
+
};
|
|
2185
|
+
});
|
|
2073
2186
|
}
|
|
2074
2187
|
async getActivityRecords() {
|
|
2075
2188
|
try {
|
|
@@ -2349,8 +2462,18 @@ Currently logged-in as ${this._username}.`
|
|
|
2349
2462
|
}
|
|
2350
2463
|
this.setDBandQ();
|
|
2351
2464
|
this.syncStrategy.startSync(this.localDB, this.remoteDB);
|
|
2352
|
-
|
|
2353
|
-
|
|
2465
|
+
this.applyDesignDocs().catch((error) => {
|
|
2466
|
+
log3(`Error in applyDesignDocs background task: ${error}`);
|
|
2467
|
+
if (error && typeof error === "object") {
|
|
2468
|
+
log3(`Full error details in applyDesignDocs: ${JSON.stringify(error)}`);
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
2471
|
+
this.deduplicateReviews().catch((error) => {
|
|
2472
|
+
log3(`Error in deduplicateReviews background task: ${error}`);
|
|
2473
|
+
if (error && typeof error === "object") {
|
|
2474
|
+
log3(`Full error details in background task: ${JSON.stringify(error)}`);
|
|
2475
|
+
}
|
|
2476
|
+
});
|
|
2354
2477
|
_BaseUser._initialized = true;
|
|
2355
2478
|
}
|
|
2356
2479
|
static designDocs = [
|
|
@@ -2368,10 +2491,15 @@ Currently logged-in as ${this._username}.`
|
|
|
2368
2491
|
}
|
|
2369
2492
|
];
|
|
2370
2493
|
async applyDesignDocs() {
|
|
2494
|
+
log3(`Starting applyDesignDocs for user: ${this._username}`);
|
|
2495
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
2371
2496
|
if (this._username === "admin") {
|
|
2497
|
+
log3("Skipping design docs for admin user");
|
|
2372
2498
|
return;
|
|
2373
2499
|
}
|
|
2500
|
+
log3(`Applying ${_BaseUser.designDocs.length} design docs`);
|
|
2374
2501
|
for (const doc of _BaseUser.designDocs) {
|
|
2502
|
+
log3(`Applying design doc: ${doc._id}`);
|
|
2375
2503
|
try {
|
|
2376
2504
|
try {
|
|
2377
2505
|
const existingDoc = await this.remoteDB.get(doc._id);
|
|
@@ -2470,8 +2598,13 @@ Currently logged-in as ${this._username}.`
|
|
|
2470
2598
|
async deduplicateReviews() {
|
|
2471
2599
|
try {
|
|
2472
2600
|
log3("Starting deduplication of scheduled reviews...");
|
|
2601
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
2602
|
+
log3(`Write DB name: ${this.writeDB.name || "unknown"}`);
|
|
2473
2603
|
const reviewsMap = {};
|
|
2474
2604
|
const duplicateDocIds = [];
|
|
2605
|
+
log3(
|
|
2606
|
+
`Attempting to query remoteDB for reviewCards/reviewCards. Database: ${this.remoteDB.name || "unknown"}`
|
|
2607
|
+
);
|
|
2475
2608
|
const scheduledReviews = await this.remoteDB.query("reviewCards/reviewCards");
|
|
2476
2609
|
log3(`Found ${scheduledReviews.rows.length} scheduled reviews to process`);
|
|
2477
2610
|
scheduledReviews.rows.forEach((r) => {
|
|
@@ -2506,6 +2639,17 @@ Currently logged-in as ${this._username}.`
|
|
|
2506
2639
|
}
|
|
2507
2640
|
} catch (error) {
|
|
2508
2641
|
log3(`Error during review deduplication: ${error}`);
|
|
2642
|
+
if (error && typeof error === "object" && "status" in error && error.status === 404) {
|
|
2643
|
+
log3(
|
|
2644
|
+
`Database not found (404) during review deduplication. Database: ${this.remoteDB.name || "unknown"}`
|
|
2645
|
+
);
|
|
2646
|
+
log3(
|
|
2647
|
+
`This might indicate the user database doesn't exist or the reviewCards view isn't available`
|
|
2648
|
+
);
|
|
2649
|
+
}
|
|
2650
|
+
if (error && typeof error === "object") {
|
|
2651
|
+
log3(`Full error details: ${JSON.stringify(error)}`);
|
|
2652
|
+
}
|
|
2509
2653
|
}
|
|
2510
2654
|
}
|
|
2511
2655
|
/**
|
|
@@ -2698,7 +2842,7 @@ var init_adminDB2 = __esm({
|
|
|
2698
2842
|
constructor() {
|
|
2699
2843
|
this.usersDB = new pouchdb_setup_default(
|
|
2700
2844
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + "_users",
|
|
2701
|
-
|
|
2845
|
+
createPouchDBConfig()
|
|
2702
2846
|
);
|
|
2703
2847
|
}
|
|
2704
2848
|
async getUsers() {
|
|
@@ -2760,9 +2904,10 @@ import fetch from "cross-fetch";
|
|
|
2760
2904
|
async function getCurrentSession() {
|
|
2761
2905
|
try {
|
|
2762
2906
|
if (ENV.COUCHDB_SERVER_URL === NOT_SET || ENV.COUCHDB_SERVER_PROTOCOL === NOT_SET) {
|
|
2763
|
-
throw new Error(
|
|
2907
|
+
throw new Error(`CouchDB server configuration not properly initialized. Protocol: "${ENV.COUCHDB_SERVER_PROTOCOL}", URL: "${ENV.COUCHDB_SERVER_URL}"`);
|
|
2764
2908
|
}
|
|
2765
|
-
const
|
|
2909
|
+
const baseUrl = ENV.COUCHDB_SERVER_URL.endsWith("/") ? ENV.COUCHDB_SERVER_URL.slice(0, -1) : ENV.COUCHDB_SERVER_URL;
|
|
2910
|
+
const url = `${ENV.COUCHDB_SERVER_PROTOCOL}://${baseUrl}/_session`;
|
|
2766
2911
|
logger.debug(`Attempting session check at: ${url}`);
|
|
2767
2912
|
const response = await fetch(url, {
|
|
2768
2913
|
method: "GET",
|
|
@@ -2774,8 +2919,10 @@ async function getCurrentSession() {
|
|
|
2774
2919
|
const resp = await response.json();
|
|
2775
2920
|
return resp;
|
|
2776
2921
|
} catch (error) {
|
|
2777
|
-
|
|
2778
|
-
|
|
2922
|
+
const baseUrl = ENV.COUCHDB_SERVER_URL.endsWith("/") ? ENV.COUCHDB_SERVER_URL.slice(0, -1) : ENV.COUCHDB_SERVER_URL;
|
|
2923
|
+
const url = `${ENV.COUCHDB_SERVER_PROTOCOL}://${baseUrl}/_session`;
|
|
2924
|
+
logger.error(`Session check error attempting to connect to: ${url} - ${error}`);
|
|
2925
|
+
throw new Error(`Session check failed connecting to ${url}: ${error}`);
|
|
2779
2926
|
}
|
|
2780
2927
|
}
|
|
2781
2928
|
async function getLoggedInUsername() {
|
|
@@ -2964,7 +3111,7 @@ var init_CouchDBSyncStrategy = __esm({
|
|
|
2964
3111
|
log4(`Fetching user database: ${dbName} (${username})`);
|
|
2965
3112
|
const ret = new pouchdb_setup_default(
|
|
2966
3113
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
2967
|
-
|
|
3114
|
+
createPouchDBConfig()
|
|
2968
3115
|
);
|
|
2969
3116
|
if (guestAccount) {
|
|
2970
3117
|
updateGuestAccountExpirationDate(ret);
|
|
@@ -2988,16 +3135,35 @@ function hexEncode2(str) {
|
|
|
2988
3135
|
}
|
|
2989
3136
|
return returnStr;
|
|
2990
3137
|
}
|
|
3138
|
+
function createPouchDBConfig() {
|
|
3139
|
+
const hasExplicitCredentials = ENV.COUCHDB_USERNAME && ENV.COUCHDB_PASSWORD;
|
|
3140
|
+
const isNodeEnvironment = typeof window === "undefined";
|
|
3141
|
+
if (hasExplicitCredentials && isNodeEnvironment) {
|
|
3142
|
+
return {
|
|
3143
|
+
fetch(url, opts = {}) {
|
|
3144
|
+
const basicAuth = btoa(`${ENV.COUCHDB_USERNAME}:${ENV.COUCHDB_PASSWORD}`);
|
|
3145
|
+
const headers = new Headers(opts.headers || {});
|
|
3146
|
+
headers.set("Authorization", `Basic ${basicAuth}`);
|
|
3147
|
+
const newOpts = {
|
|
3148
|
+
...opts,
|
|
3149
|
+
headers
|
|
3150
|
+
};
|
|
3151
|
+
return pouchdb_setup_default.fetch(url, newOpts);
|
|
3152
|
+
}
|
|
3153
|
+
};
|
|
3154
|
+
}
|
|
3155
|
+
return pouchDBincludeCredentialsConfig;
|
|
3156
|
+
}
|
|
2991
3157
|
function getCouchDB(dbName) {
|
|
2992
3158
|
return new pouchdb_setup_default(
|
|
2993
3159
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
2994
|
-
|
|
3160
|
+
createPouchDBConfig()
|
|
2995
3161
|
);
|
|
2996
3162
|
}
|
|
2997
3163
|
function getCourseDB2(courseID) {
|
|
2998
3164
|
return new pouchdb_setup_default(
|
|
2999
3165
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + "coursedb-" + courseID,
|
|
3000
|
-
|
|
3166
|
+
createPouchDBConfig()
|
|
3001
3167
|
);
|
|
3002
3168
|
}
|
|
3003
3169
|
async function getLatestVersion() {
|
|
@@ -3082,7 +3248,7 @@ function getCouchUserDB(username) {
|
|
|
3082
3248
|
log(`Fetching user database: ${dbName} (${username})`);
|
|
3083
3249
|
const ret = new pouchdb_setup_default(
|
|
3084
3250
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
3085
|
-
|
|
3251
|
+
createPouchDBConfig()
|
|
3086
3252
|
);
|
|
3087
3253
|
if (guestAccount) {
|
|
3088
3254
|
updateGuestAccountExpirationDate2(ret);
|
|
@@ -3161,6 +3327,7 @@ export {
|
|
|
3161
3327
|
TeacherClassroomDB,
|
|
3162
3328
|
addNote55,
|
|
3163
3329
|
addTagToCard,
|
|
3330
|
+
createPouchDBConfig,
|
|
3164
3331
|
createTag,
|
|
3165
3332
|
deleteTag,
|
|
3166
3333
|
filterAllDocsByPrefix,
|
|
@@ -3187,7 +3354,6 @@ export {
|
|
|
3187
3354
|
hexEncode2 as hexEncode,
|
|
3188
3355
|
isReview,
|
|
3189
3356
|
localUserDB,
|
|
3190
|
-
pouchDBincludeCredentialsConfig,
|
|
3191
3357
|
removeTagFromCard,
|
|
3192
3358
|
scheduleCardReview,
|
|
3193
3359
|
updateCardElo2 as updateCardElo,
|