@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.
Files changed (68) hide show
  1. package/dist/core/index.d.mts +5 -5
  2. package/dist/core/index.d.ts +5 -5
  3. package/dist/core/index.js +212 -50
  4. package/dist/core/index.js.map +1 -1
  5. package/dist/core/index.mjs +212 -50
  6. package/dist/core/index.mjs.map +1 -1
  7. package/dist/{dataLayerProvider-DqtNroSh.d.ts → dataLayerProvider-VieuAAkV.d.mts} +8 -1
  8. package/dist/{dataLayerProvider-BInqI_RF.d.mts → dataLayerProvider-juuqUHOP.d.ts} +8 -1
  9. package/dist/impl/couch/index.d.mts +19 -7
  10. package/dist/impl/couch/index.d.ts +19 -7
  11. package/dist/impl/couch/index.js +229 -63
  12. package/dist/impl/couch/index.js.map +1 -1
  13. package/dist/impl/couch/index.mjs +228 -62
  14. package/dist/impl/couch/index.mjs.map +1 -1
  15. package/dist/impl/static/index.d.mts +13 -6
  16. package/dist/impl/static/index.d.ts +13 -6
  17. package/dist/impl/static/index.js +142 -46
  18. package/dist/impl/static/index.js.map +1 -1
  19. package/dist/impl/static/index.mjs +142 -46
  20. package/dist/impl/static/index.mjs.map +1 -1
  21. package/dist/{index-CLL31bEy.d.ts → index-CWY6yhkV.d.ts} +1 -1
  22. package/dist/{index-CUNnL38E.d.mts → index-DZyxHCcf.d.mts} +1 -1
  23. package/dist/index.d.mts +28 -20
  24. package/dist/index.d.ts +28 -20
  25. package/dist/index.js +374 -108
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +378 -108
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/pouch/index.d.mts +1 -0
  30. package/dist/pouch/index.d.ts +1 -0
  31. package/dist/pouch/index.js +49 -0
  32. package/dist/pouch/index.js.map +1 -0
  33. package/dist/pouch/index.mjs +16 -0
  34. package/dist/pouch/index.mjs.map +1 -0
  35. package/dist/{types-DC-ckZug.d.mts → types-Che4wTwA.d.mts} +1 -1
  36. package/dist/{types-BefDGkKa.d.ts → types-DtoI27Xh.d.ts} +1 -1
  37. package/dist/{types-legacy-Birv-Jx6.d.mts → types-legacy-B8ahaCbj.d.mts} +5 -1
  38. package/dist/{types-legacy-Birv-Jx6.d.ts → types-legacy-B8ahaCbj.d.ts} +5 -1
  39. package/dist/{userDB-C33Hzjgn.d.mts → userDB-B7zTQ123.d.ts} +88 -55
  40. package/dist/{userDB-DusL7OXe.d.ts → userDB-DJ8HMw83.d.mts} +88 -55
  41. package/dist/util/packer/index.d.mts +3 -3
  42. package/dist/util/packer/index.d.ts +3 -3
  43. package/package.json +3 -3
  44. package/src/core/interfaces/contentSource.ts +3 -2
  45. package/src/core/interfaces/courseDB.ts +26 -3
  46. package/src/core/interfaces/dataLayerProvider.ts +9 -1
  47. package/src/core/interfaces/userDB.ts +80 -64
  48. package/src/core/navigators/elo.ts +10 -7
  49. package/src/core/navigators/index.ts +1 -1
  50. package/src/core/types/types-legacy.ts +5 -0
  51. package/src/impl/common/BaseUserDB.ts +45 -3
  52. package/src/impl/couch/CouchDBSyncStrategy.ts +2 -2
  53. package/src/impl/couch/PouchDataLayerProvider.ts +21 -0
  54. package/src/impl/couch/adminDB.ts +2 -2
  55. package/src/impl/couch/auth.ts +13 -4
  56. package/src/impl/couch/classroomDB.ts +10 -12
  57. package/src/impl/couch/courseAPI.ts +2 -2
  58. package/src/impl/couch/courseDB.ts +130 -11
  59. package/src/impl/couch/courseLookupDB.ts +4 -3
  60. package/src/impl/couch/index.ts +36 -4
  61. package/src/impl/couch/pouchdb-setup.ts +3 -3
  62. package/src/impl/couch/updateQueue.ts +51 -33
  63. package/src/impl/static/StaticDataLayerProvider.ts +11 -0
  64. package/src/impl/static/courseDB.ts +47 -8
  65. package/src/pouch/index.ts +2 -0
  66. package/src/study/SessionController.ts +168 -51
  67. package/src/study/SpacedRepetition.ts +1 -1
  68. package/tsup.config.ts +1 -0
@@ -1,8 +1,8 @@
1
- import { h as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, d as ContentNavigationStrategyData, e as StudySessionReviewItem, f as ScheduledCard, S as StudySessionNewItem } from '../userDB-C33Hzjgn.mjs';
2
- export { B as ActivityRecord, A as AdminDBInterface, s as AssignedCard, g as AssignedContent, r as AssignedCourse, q as AssignedTag, b as ClassroomDBInterface, x as ClassroomRegistration, w as ClassroomRegistrationDesignation, y as ClassroomRegistrationDoc, o as ContentSourceID, c as CourseInfo, E as CourseRegistration, F as CourseRegistrationDoc, a as CoursesDBInterface, i as StudentClassroomDBInterface, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, j as StudySessionItem, T as TeacherClassroomDBInterface, z as UserConfig, u as UserCourseSetting, t as UserCourseSettings, v as UsrCrsDataInterface, p as getStudySource, n as isReview } from '../userDB-C33Hzjgn.mjs';
3
- export { D as DataLayerProvider } from '../dataLayerProvider-BInqI_RF.mjs';
4
- import { g as CardHistory, C as CardRecord, h as QuestionRecord } from '../types-legacy-Birv-Jx6.mjs';
5
- export { b as CardData, c as CourseListData, e as DataShapeData, d as DisplayableData, D as DocType, f as DocTypePrefixes, F as Field, G as GuestUsername, Q as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-Birv-Jx6.mjs';
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
 
@@ -1,8 +1,8 @@
1
- import { h as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, d as ContentNavigationStrategyData, e as StudySessionReviewItem, f as ScheduledCard, S as StudySessionNewItem } from '../userDB-DusL7OXe.js';
2
- export { B as ActivityRecord, A as AdminDBInterface, s as AssignedCard, g as AssignedContent, r as AssignedCourse, q as AssignedTag, b as ClassroomDBInterface, x as ClassroomRegistration, w as ClassroomRegistrationDesignation, y as ClassroomRegistrationDoc, o as ContentSourceID, c as CourseInfo, E as CourseRegistration, F as CourseRegistrationDoc, a as CoursesDBInterface, i as StudentClassroomDBInterface, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, j as StudySessionItem, T as TeacherClassroomDBInterface, z as UserConfig, u as UserCourseSetting, t as UserCourseSettings, v as UsrCrsDataInterface, p as getStudySource, n as isReview } from '../userDB-DusL7OXe.js';
3
- export { D as DataLayerProvider } from '../dataLayerProvider-DqtNroSh.js';
4
- import { g as CardHistory, C as CardRecord, h as QuestionRecord } from '../types-legacy-Birv-Jx6.js';
5
- export { b as CardData, c as CourseListData, e as DataShapeData, d as DisplayableData, D as DocType, f as DocTypePrefixes, F as Field, G as GuestUsername, Q as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-Birv-Jx6.js';
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
 
@@ -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
- timeout: 6e4
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
- try {
352
- let doc = await this.readDB.get(id);
353
- logger.debug(`Retrieved doc: ${id}`);
354
- while (this.pendingUpdates[id].length !== 0) {
355
- const update = this.pendingUpdates[id].splice(0, 1)[0];
356
- if (typeof update === "function") {
357
- doc = { ...doc, ...update(doc) };
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
- doc = {
360
- ...doc,
361
- ...update
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
- pouchDBincludeCredentialsConfig
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({ limit, elo: "user" }, (c) => {
717
- if (activeCards.some((ac) => c.includes(ac))) {
718
- return false;
719
- } else {
720
- return true;
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
- })).map((c) => {
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", ".ts"];
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) => `${this.id}-${c.id}-${c.key}`);
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(this.id, cardId, tagId, (await this._getCurrentUser()).getUsername(), updateELO);
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: split[1],
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
- pouchDBincludeCredentialsConfig
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(`New Cards from classroom ${this._cfg.name}: ${ret.map((c) => c.qualifiedID)}`);
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.qualifiedID.includes(ac))) {
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
- pouchDBincludeCredentialsConfig
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) => `${r.doc.courseId}-${r.doc.cardId}`);
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
- void this.applyDesignDocs();
2098
- void this.deduplicateReviews();
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
  /**