@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
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { U as UserDBInterface, C as CourseDBInterface,
|
|
2
|
-
import { D as DataLayerProvider } from '../../dataLayerProvider-
|
|
3
|
-
import { S as StaticCourseManifest } from '../../types-
|
|
1
|
+
import { U as UserDBInterface, C as CourseDBInterface, b as CoursesDBInterface, c as ClassroomDBInterface, A as AdminDBInterface, a as UserDBReader, d as CourseInfo, S as StudySessionNewItem, D as DataLayerResult, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard } from '../../userDB-DJ8HMw83.mjs';
|
|
2
|
+
import { D as DataLayerProvider } from '../../dataLayerProvider-VieuAAkV.mjs';
|
|
3
|
+
import { S as StaticCourseManifest } from '../../types-Che4wTwA.mjs';
|
|
4
4
|
import { CourseConfig, CourseElo, DataShape } from '@vue-skuilder/common';
|
|
5
|
-
import { S as SkuilderCourseData, T as TagStub, a as Tag } from '../../types-legacy-
|
|
5
|
+
import { S as SkuilderCourseData, Q as QualifiedCardID, T as TagStub, a as Tag } from '../../types-legacy-B8ahaCbj.mjs';
|
|
6
6
|
import { S as SyncStrategy, A as AccountCreationResult, a as AuthenticationResult } from '../../SyncStrategy-CyATpyLQ.mjs';
|
|
7
7
|
import 'moment';
|
|
8
8
|
|
|
@@ -23,6 +23,7 @@ declare class StaticDataLayerProvider implements DataLayerProvider {
|
|
|
23
23
|
getCoursesDB(): CoursesDBInterface;
|
|
24
24
|
getClassroomDB(_classId: string, _type: 'student' | 'teacher'): Promise<ClassroomDBInterface>;
|
|
25
25
|
getAdminDB(): AdminDBInterface;
|
|
26
|
+
createUserReaderForUser(targetUsername: string): Promise<UserDBReader>;
|
|
26
27
|
isReadOnly(): boolean;
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -118,14 +119,18 @@ declare class StaticCourseDB implements CourseDBInterface {
|
|
|
118
119
|
getCourseInfo(): Promise<CourseInfo>;
|
|
119
120
|
getCourseDoc<T extends SkuilderCourseData>(id: string, _options?: PouchDB.Core.GetOptions): Promise<T>;
|
|
120
121
|
getCourseDocs<T extends SkuilderCourseData>(ids: string[], _options?: PouchDB.Core.AllDocsOptions): Promise<PouchDB.Core.AllDocsWithKeysResponse<{} & T>>;
|
|
121
|
-
getCardsByELO(elo: number, limit?: number): Promise<
|
|
122
|
+
getCardsByELO(elo: number, limit?: number): Promise<{
|
|
123
|
+
courseID: string;
|
|
124
|
+
cardID: string;
|
|
125
|
+
elo?: number;
|
|
126
|
+
}[]>;
|
|
122
127
|
getCardEloData(cardIds: string[]): Promise<CourseElo[]>;
|
|
123
128
|
updateCardElo(cardId: string, _elo: CourseElo): Promise<PouchDB.Core.Response>;
|
|
124
129
|
getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
|
|
125
130
|
getCardsCenteredAtELO(options: {
|
|
126
131
|
limit: number;
|
|
127
132
|
elo: 'user' | 'random' | number;
|
|
128
|
-
}, filter?: (id:
|
|
133
|
+
}, filter?: (id: QualifiedCardID) => boolean): Promise<StudySessionNewItem[]>;
|
|
129
134
|
getAppliedTags(cardId: string): Promise<PouchDB.Query.Response<TagStub>>;
|
|
130
135
|
addTagToCard(_cardId: string, _tagId: string): Promise<PouchDB.Core.Response>;
|
|
131
136
|
removeTagFromCard(_cardId: string, _tagId: string): Promise<PouchDB.Core.Response>;
|
|
@@ -154,6 +159,8 @@ declare class StaticCourseDB implements CourseDBInterface {
|
|
|
154
159
|
* Internal helper method for static attachment serving
|
|
155
160
|
*/
|
|
156
161
|
getAttachmentBlob(docId: string, attachmentName: string): Promise<Blob | Buffer | null>;
|
|
162
|
+
searchCards(_query: string): Promise<any[]>;
|
|
163
|
+
find(_request: PouchDB.Find.FindRequest<any>): Promise<PouchDB.Find.FindResponse<any>>;
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
declare class StaticCoursesDB implements CoursesDBInterface {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { U as UserDBInterface, C as CourseDBInterface,
|
|
2
|
-
import { D as DataLayerProvider } from '../../dataLayerProvider-
|
|
3
|
-
import { S as StaticCourseManifest } from '../../types-
|
|
1
|
+
import { U as UserDBInterface, C as CourseDBInterface, b as CoursesDBInterface, c as ClassroomDBInterface, A as AdminDBInterface, a as UserDBReader, d as CourseInfo, S as StudySessionNewItem, D as DataLayerResult, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard } from '../../userDB-B7zTQ123.js';
|
|
2
|
+
import { D as DataLayerProvider } from '../../dataLayerProvider-juuqUHOP.js';
|
|
3
|
+
import { S as StaticCourseManifest } from '../../types-DtoI27Xh.js';
|
|
4
4
|
import { CourseConfig, CourseElo, DataShape } from '@vue-skuilder/common';
|
|
5
|
-
import { S as SkuilderCourseData, T as TagStub, a as Tag } from '../../types-legacy-
|
|
5
|
+
import { S as SkuilderCourseData, Q as QualifiedCardID, T as TagStub, a as Tag } from '../../types-legacy-B8ahaCbj.js';
|
|
6
6
|
import { S as SyncStrategy, A as AccountCreationResult, a as AuthenticationResult } from '../../SyncStrategy-CyATpyLQ.js';
|
|
7
7
|
import 'moment';
|
|
8
8
|
|
|
@@ -23,6 +23,7 @@ declare class StaticDataLayerProvider implements DataLayerProvider {
|
|
|
23
23
|
getCoursesDB(): CoursesDBInterface;
|
|
24
24
|
getClassroomDB(_classId: string, _type: 'student' | 'teacher'): Promise<ClassroomDBInterface>;
|
|
25
25
|
getAdminDB(): AdminDBInterface;
|
|
26
|
+
createUserReaderForUser(targetUsername: string): Promise<UserDBReader>;
|
|
26
27
|
isReadOnly(): boolean;
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -118,14 +119,18 @@ declare class StaticCourseDB implements CourseDBInterface {
|
|
|
118
119
|
getCourseInfo(): Promise<CourseInfo>;
|
|
119
120
|
getCourseDoc<T extends SkuilderCourseData>(id: string, _options?: PouchDB.Core.GetOptions): Promise<T>;
|
|
120
121
|
getCourseDocs<T extends SkuilderCourseData>(ids: string[], _options?: PouchDB.Core.AllDocsOptions): Promise<PouchDB.Core.AllDocsWithKeysResponse<{} & T>>;
|
|
121
|
-
getCardsByELO(elo: number, limit?: number): Promise<
|
|
122
|
+
getCardsByELO(elo: number, limit?: number): Promise<{
|
|
123
|
+
courseID: string;
|
|
124
|
+
cardID: string;
|
|
125
|
+
elo?: number;
|
|
126
|
+
}[]>;
|
|
122
127
|
getCardEloData(cardIds: string[]): Promise<CourseElo[]>;
|
|
123
128
|
updateCardElo(cardId: string, _elo: CourseElo): Promise<PouchDB.Core.Response>;
|
|
124
129
|
getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
|
|
125
130
|
getCardsCenteredAtELO(options: {
|
|
126
131
|
limit: number;
|
|
127
132
|
elo: 'user' | 'random' | number;
|
|
128
|
-
}, filter?: (id:
|
|
133
|
+
}, filter?: (id: QualifiedCardID) => boolean): Promise<StudySessionNewItem[]>;
|
|
129
134
|
getAppliedTags(cardId: string): Promise<PouchDB.Query.Response<TagStub>>;
|
|
130
135
|
addTagToCard(_cardId: string, _tagId: string): Promise<PouchDB.Core.Response>;
|
|
131
136
|
removeTagFromCard(_cardId: string, _tagId: string): Promise<PouchDB.Core.Response>;
|
|
@@ -154,6 +159,8 @@ declare class StaticCourseDB implements CourseDBInterface {
|
|
|
154
159
|
* Internal helper method for static attachment serving
|
|
155
160
|
*/
|
|
156
161
|
getAttachmentBlob(docId: string, attachmentName: string): Promise<Blob | Buffer | null>;
|
|
162
|
+
searchCards(_query: string): Promise<any[]>;
|
|
163
|
+
find(_request: PouchDB.Find.FindRequest<any>): Promise<PouchDB.Find.FindResponse<any>>;
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
declare class StaticCoursesDB implements CoursesDBInterface {
|
|
@@ -146,9 +146,9 @@ var init_pouchdb_setup = __esm({
|
|
|
146
146
|
import_pouchdb.default.plugin(import_pouchdb_find.default);
|
|
147
147
|
import_pouchdb.default.plugin(import_pouchdb_authentication.default);
|
|
148
148
|
import_pouchdb.default.defaults({
|
|
149
|
-
ajax: {
|
|
150
|
-
|
|
151
|
-
}
|
|
149
|
+
// ajax: {
|
|
150
|
+
// timeout: 60000,
|
|
151
|
+
// },
|
|
152
152
|
});
|
|
153
153
|
pouchdb_setup_default = import_pouchdb.default;
|
|
154
154
|
}
|
|
@@ -307,37 +307,48 @@ var init_updateQueue = __esm({
|
|
|
307
307
|
} else {
|
|
308
308
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
309
309
|
this.inprogressUpdates[id] = true;
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
310
|
+
const MAX_RETRIES = 5;
|
|
311
|
+
for (let i = 0; i < MAX_RETRIES; i++) {
|
|
312
|
+
try {
|
|
313
|
+
const doc = await this.readDB.get(id);
|
|
314
|
+
logger.debug(`Retrieved doc: ${id}`);
|
|
315
|
+
let updatedDoc = { ...doc };
|
|
316
|
+
const updatesToApply = [...this.pendingUpdates[id]];
|
|
317
|
+
for (const update of updatesToApply) {
|
|
318
|
+
if (typeof update === "function") {
|
|
319
|
+
updatedDoc = { ...updatedDoc, ...update(updatedDoc) };
|
|
320
|
+
} else {
|
|
321
|
+
updatedDoc = {
|
|
322
|
+
...updatedDoc,
|
|
323
|
+
...update
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
await this.writeDB.put(updatedDoc);
|
|
328
|
+
logger.debug(`Put doc: ${id}`);
|
|
329
|
+
this.pendingUpdates[id].splice(0, updatesToApply.length);
|
|
330
|
+
if (this.pendingUpdates[id].length === 0) {
|
|
331
|
+
this.inprogressUpdates[id] = false;
|
|
332
|
+
delete this.inprogressUpdates[id];
|
|
317
333
|
} else {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
334
|
+
return this.applyUpdates(id);
|
|
335
|
+
}
|
|
336
|
+
return updatedDoc;
|
|
337
|
+
} catch (e) {
|
|
338
|
+
if (e.name === "conflict" && i < MAX_RETRIES - 1) {
|
|
339
|
+
logger.warn(`Conflict on update for doc ${id}, retry #${i + 1}`);
|
|
340
|
+
await new Promise((res) => setTimeout(res, 50 * Math.random()));
|
|
341
|
+
} else {
|
|
342
|
+
delete this.inprogressUpdates[id];
|
|
343
|
+
if (this.pendingUpdates[id]) {
|
|
344
|
+
delete this.pendingUpdates[id];
|
|
345
|
+
}
|
|
346
|
+
logger.error(`Error on attemped update (retry ${i}): ${JSON.stringify(e)}`);
|
|
347
|
+
throw e;
|
|
322
348
|
}
|
|
323
349
|
}
|
|
324
|
-
await this.writeDB.put(doc);
|
|
325
|
-
logger.debug(`Put doc: ${id}`);
|
|
326
|
-
if (this.pendingUpdates[id].length === 0) {
|
|
327
|
-
this.inprogressUpdates[id] = false;
|
|
328
|
-
delete this.inprogressUpdates[id];
|
|
329
|
-
} else {
|
|
330
|
-
return this.applyUpdates(id);
|
|
331
|
-
}
|
|
332
|
-
return doc;
|
|
333
|
-
} catch (e) {
|
|
334
|
-
delete this.inprogressUpdates[id];
|
|
335
|
-
if (this.pendingUpdates[id]) {
|
|
336
|
-
delete this.pendingUpdates[id];
|
|
337
|
-
}
|
|
338
|
-
logger.error(`Error on attemped update: ${JSON.stringify(e)}`);
|
|
339
|
-
throw e;
|
|
340
350
|
}
|
|
351
|
+
throw new Error(`UpdateQueue failed for doc ${id} after ${MAX_RETRIES} retries.`);
|
|
341
352
|
} else {
|
|
342
353
|
throw new Error(`Empty Updates Queue Triggered`);
|
|
343
354
|
}
|
|
@@ -425,7 +436,7 @@ function getCourseDB(courseID) {
|
|
|
425
436
|
const dbName = `coursedb-${courseID}`;
|
|
426
437
|
return new pouchdb_setup_default(
|
|
427
438
|
ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + dbName,
|
|
428
|
-
|
|
439
|
+
createPouchDBConfig()
|
|
429
440
|
);
|
|
430
441
|
}
|
|
431
442
|
var import_common, import_common2, import_common3, import_uuid;
|
|
@@ -503,13 +514,16 @@ var init_elo = __esm({
|
|
|
503
514
|
}
|
|
504
515
|
async getNewCards(limit = 99) {
|
|
505
516
|
const activeCards = await this.user.getActiveCards();
|
|
506
|
-
return (await this.course.getCardsCenteredAtELO(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
517
|
+
return (await this.course.getCardsCenteredAtELO(
|
|
518
|
+
{ limit, elo: "user" },
|
|
519
|
+
(c) => {
|
|
520
|
+
if (activeCards.some((ac) => c.cardID === ac.cardID)) {
|
|
521
|
+
return false;
|
|
522
|
+
} else {
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
511
525
|
}
|
|
512
|
-
|
|
526
|
+
)).map((c) => {
|
|
513
527
|
return {
|
|
514
528
|
...c,
|
|
515
529
|
status: "new"
|
|
@@ -557,7 +571,7 @@ var init_navigators = __esm({
|
|
|
557
571
|
static async create(user, course, strategyData) {
|
|
558
572
|
const implementingClass = strategyData.implementingClass;
|
|
559
573
|
let NavigatorImpl;
|
|
560
|
-
const variations = ["", ".js", "
|
|
574
|
+
const variations = [".ts", ".js", ""];
|
|
561
575
|
for (const ext of variations) {
|
|
562
576
|
try {
|
|
563
577
|
const module2 = await globImport(`./${implementingClass}${ext}`);
|
|
@@ -649,6 +663,25 @@ var init_CouchDBSyncStrategy = __esm({
|
|
|
649
663
|
});
|
|
650
664
|
|
|
651
665
|
// src/impl/couch/index.ts
|
|
666
|
+
function createPouchDBConfig() {
|
|
667
|
+
const hasExplicitCredentials = ENV.COUCHDB_USERNAME && ENV.COUCHDB_PASSWORD;
|
|
668
|
+
const isNodeEnvironment = typeof window === "undefined";
|
|
669
|
+
if (hasExplicitCredentials && isNodeEnvironment) {
|
|
670
|
+
return {
|
|
671
|
+
fetch(url, opts = {}) {
|
|
672
|
+
const basicAuth = btoa(`${ENV.COUCHDB_USERNAME}:${ENV.COUCHDB_PASSWORD}`);
|
|
673
|
+
const headers = new Headers(opts.headers || {});
|
|
674
|
+
headers.set("Authorization", `Basic ${basicAuth}`);
|
|
675
|
+
const newOpts = {
|
|
676
|
+
...opts,
|
|
677
|
+
headers
|
|
678
|
+
};
|
|
679
|
+
return pouchdb_setup_default.fetch(url, newOpts);
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
return pouchDBincludeCredentialsConfig;
|
|
684
|
+
}
|
|
652
685
|
var import_cross_fetch2, import_moment4, import_process, isBrowser, GUEST_LOCAL_DB, localUserDB, pouchDBincludeCredentialsConfig;
|
|
653
686
|
var init_couch = __esm({
|
|
654
687
|
"src/impl/couch/index.ts"() {
|
|
@@ -911,6 +944,9 @@ Currently logged-in as ${this._username}.`
|
|
|
911
944
|
await this.init();
|
|
912
945
|
return ret;
|
|
913
946
|
}
|
|
947
|
+
async get(id) {
|
|
948
|
+
return this.localDB.get(id);
|
|
949
|
+
}
|
|
914
950
|
update(id, update) {
|
|
915
951
|
return this.updateQueue.update(id, update);
|
|
916
952
|
}
|
|
@@ -957,7 +993,12 @@ Currently logged-in as ${this._username}.`
|
|
|
957
993
|
endkey: keys.endkey,
|
|
958
994
|
include_docs: true
|
|
959
995
|
});
|
|
960
|
-
return reviews.rows.map((r) =>
|
|
996
|
+
return reviews.rows.map((r) => {
|
|
997
|
+
return {
|
|
998
|
+
courseID: r.doc.courseId,
|
|
999
|
+
cardID: r.doc.cardId
|
|
1000
|
+
};
|
|
1001
|
+
});
|
|
961
1002
|
}
|
|
962
1003
|
async getActivityRecords() {
|
|
963
1004
|
try {
|
|
@@ -1237,8 +1278,18 @@ Currently logged-in as ${this._username}.`
|
|
|
1237
1278
|
}
|
|
1238
1279
|
this.setDBandQ();
|
|
1239
1280
|
this.syncStrategy.startSync(this.localDB, this.remoteDB);
|
|
1240
|
-
|
|
1241
|
-
|
|
1281
|
+
this.applyDesignDocs().catch((error) => {
|
|
1282
|
+
log3(`Error in applyDesignDocs background task: ${error}`);
|
|
1283
|
+
if (error && typeof error === "object") {
|
|
1284
|
+
log3(`Full error details in applyDesignDocs: ${JSON.stringify(error)}`);
|
|
1285
|
+
}
|
|
1286
|
+
});
|
|
1287
|
+
this.deduplicateReviews().catch((error) => {
|
|
1288
|
+
log3(`Error in deduplicateReviews background task: ${error}`);
|
|
1289
|
+
if (error && typeof error === "object") {
|
|
1290
|
+
log3(`Full error details in background task: ${JSON.stringify(error)}`);
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1242
1293
|
_BaseUser._initialized = true;
|
|
1243
1294
|
}
|
|
1244
1295
|
static designDocs = [
|
|
@@ -1256,10 +1307,15 @@ Currently logged-in as ${this._username}.`
|
|
|
1256
1307
|
}
|
|
1257
1308
|
];
|
|
1258
1309
|
async applyDesignDocs() {
|
|
1310
|
+
log3(`Starting applyDesignDocs for user: ${this._username}`);
|
|
1311
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
1259
1312
|
if (this._username === "admin") {
|
|
1313
|
+
log3("Skipping design docs for admin user");
|
|
1260
1314
|
return;
|
|
1261
1315
|
}
|
|
1316
|
+
log3(`Applying ${_BaseUser.designDocs.length} design docs`);
|
|
1262
1317
|
for (const doc of _BaseUser.designDocs) {
|
|
1318
|
+
log3(`Applying design doc: ${doc._id}`);
|
|
1263
1319
|
try {
|
|
1264
1320
|
try {
|
|
1265
1321
|
const existingDoc = await this.remoteDB.get(doc._id);
|
|
@@ -1358,8 +1414,13 @@ Currently logged-in as ${this._username}.`
|
|
|
1358
1414
|
async deduplicateReviews() {
|
|
1359
1415
|
try {
|
|
1360
1416
|
log3("Starting deduplication of scheduled reviews...");
|
|
1417
|
+
log3(`Remote DB name: ${this.remoteDB.name || "unknown"}`);
|
|
1418
|
+
log3(`Write DB name: ${this.writeDB.name || "unknown"}`);
|
|
1361
1419
|
const reviewsMap = {};
|
|
1362
1420
|
const duplicateDocIds = [];
|
|
1421
|
+
log3(
|
|
1422
|
+
`Attempting to query remoteDB for reviewCards/reviewCards. Database: ${this.remoteDB.name || "unknown"}`
|
|
1423
|
+
);
|
|
1363
1424
|
const scheduledReviews = await this.remoteDB.query("reviewCards/reviewCards");
|
|
1364
1425
|
log3(`Found ${scheduledReviews.rows.length} scheduled reviews to process`);
|
|
1365
1426
|
scheduledReviews.rows.forEach((r) => {
|
|
@@ -1394,6 +1455,17 @@ Currently logged-in as ${this._username}.`
|
|
|
1394
1455
|
}
|
|
1395
1456
|
} catch (error) {
|
|
1396
1457
|
log3(`Error during review deduplication: ${error}`);
|
|
1458
|
+
if (error && typeof error === "object" && "status" in error && error.status === 404) {
|
|
1459
|
+
log3(
|
|
1460
|
+
`Database not found (404) during review deduplication. Database: ${this.remoteDB.name || "unknown"}`
|
|
1461
|
+
);
|
|
1462
|
+
log3(
|
|
1463
|
+
`This might indicate the user database doesn't exist or the reviewCards view isn't available`
|
|
1464
|
+
);
|
|
1465
|
+
}
|
|
1466
|
+
if (error && typeof error === "object") {
|
|
1467
|
+
log3(`Full error details: ${JSON.stringify(error)}`);
|
|
1468
|
+
}
|
|
1397
1469
|
}
|
|
1398
1470
|
}
|
|
1399
1471
|
/**
|
|
@@ -2098,7 +2170,10 @@ var init_courseDB3 = __esm({
|
|
|
2098
2170
|
};
|
|
2099
2171
|
}
|
|
2100
2172
|
async getCardsByELO(elo, limit) {
|
|
2101
|
-
return this.unpacker.queryByElo(elo, limit || 25)
|
|
2173
|
+
return (await this.unpacker.queryByElo(elo, limit || 25)).map((card) => {
|
|
2174
|
+
const [courseID, cardID, elo2] = card.split("-");
|
|
2175
|
+
return { courseID, cardID, elo: elo2 ? parseInt(elo2) : void 0 };
|
|
2176
|
+
});
|
|
2102
2177
|
}
|
|
2103
2178
|
async getCardEloData(cardIds) {
|
|
2104
2179
|
const results = await Promise.all(
|
|
@@ -2142,14 +2217,19 @@ var init_courseDB3 = __esm({
|
|
|
2142
2217
|
} else if (options.elo === "random") {
|
|
2143
2218
|
targetElo = 800 + Math.random() * 400;
|
|
2144
2219
|
}
|
|
2145
|
-
let cardIds = await this.unpacker.queryByElo(targetElo, options.limit * 2)
|
|
2220
|
+
let cardIds = (await this.unpacker.queryByElo(targetElo, options.limit * 2)).map((c) => {
|
|
2221
|
+
return {
|
|
2222
|
+
cardID: c,
|
|
2223
|
+
courseID: this.courseId
|
|
2224
|
+
};
|
|
2225
|
+
});
|
|
2146
2226
|
if (filter) {
|
|
2147
2227
|
cardIds = cardIds.filter(filter);
|
|
2148
2228
|
}
|
|
2149
|
-
return cardIds.slice(0, options.limit).map((
|
|
2229
|
+
return cardIds.slice(0, options.limit).map((card) => ({
|
|
2150
2230
|
status: "new",
|
|
2151
|
-
qualifiedID: `${this.courseId}-${cardId}`,
|
|
2152
|
-
cardID:
|
|
2231
|
+
// qualifiedID: `${this.courseId}-${cardId}`,
|
|
2232
|
+
cardID: card.cardID,
|
|
2153
2233
|
contentSourceType: "course",
|
|
2154
2234
|
contentSourceID: this.courseId,
|
|
2155
2235
|
courseID: this.courseId
|
|
@@ -2341,6 +2421,16 @@ var init_courseDB3 = __esm({
|
|
|
2341
2421
|
async getAttachmentBlob(docId, attachmentName) {
|
|
2342
2422
|
return this.unpacker.getAttachmentBlob(docId, attachmentName);
|
|
2343
2423
|
}
|
|
2424
|
+
// Admin search methods
|
|
2425
|
+
async searchCards(_query) {
|
|
2426
|
+
return [];
|
|
2427
|
+
}
|
|
2428
|
+
async find(_request) {
|
|
2429
|
+
return {
|
|
2430
|
+
docs: [],
|
|
2431
|
+
warning: "Find operations not supported in static mode"
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2344
2434
|
};
|
|
2345
2435
|
}
|
|
2346
2436
|
});
|
|
@@ -2492,6 +2582,12 @@ var init_StaticDataLayerProvider = __esm({
|
|
|
2492
2582
|
getAdminDB() {
|
|
2493
2583
|
throw new Error("Admin functions not supported in static mode");
|
|
2494
2584
|
}
|
|
2585
|
+
async createUserReaderForUser(targetUsername) {
|
|
2586
|
+
logger.warn(`StaticDataLayerProvider: Multi-user access not supported in static mode`);
|
|
2587
|
+
logger.warn(`Request: trying to access data for ${targetUsername}`);
|
|
2588
|
+
logger.warn(`Returning current user's data instead`);
|
|
2589
|
+
return this.getUserDB();
|
|
2590
|
+
}
|
|
2495
2591
|
isReadOnly() {
|
|
2496
2592
|
return true;
|
|
2497
2593
|
}
|