@vue-skuilder/db 0.1.7 → 0.1.8-1
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/{SyncStrategy-DnJRj-Xp.d.mts → SyncStrategy-CyATpyLQ.d.mts} +6 -0
- package/dist/{SyncStrategy-DnJRj-Xp.d.ts → SyncStrategy-CyATpyLQ.d.ts} +6 -0
- package/dist/core/index.d.mts +5 -5
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +131 -118
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +128 -115
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-BbW9EnZK.d.mts → dataLayerProvider-BInqI_RF.d.mts} +1 -1
- package/dist/{dataLayerProvider-6stCgDME.d.ts → dataLayerProvider-DqtNroSh.d.ts} +1 -1
- package/dist/impl/couch/index.d.mts +6 -6
- package/dist/impl/couch/index.d.ts +6 -6
- package/dist/impl/couch/index.js +1368 -1255
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +1362 -1249
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.mts +8 -6
- package/dist/impl/static/index.d.ts +8 -6
- package/dist/impl/static/index.js +253 -843
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +250 -842
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/index-CLL31bEy.d.ts +137 -0
- package/dist/index-CUNnL38E.d.mts +137 -0
- package/dist/index.d.mts +11 -56
- package/dist/index.d.ts +11 -56
- package/dist/index.js +346 -173
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +343 -170
- package/dist/index.mjs.map +1 -1
- package/dist/{types-BvzcRAys.d.ts → types-BefDGkKa.d.ts} +1 -1
- package/dist/{types-CQQ80R5N.d.mts → types-DC-ckZug.d.mts} +1 -1
- package/dist/{types-legacy-CtrmkOLu.d.mts → types-legacy-Birv-Jx6.d.mts} +2 -2
- package/dist/{types-legacy-CtrmkOLu.d.ts → types-legacy-Birv-Jx6.d.ts} +2 -2
- package/dist/{userDB-DUY63VMN.d.ts → userDB-C33Hzjgn.d.mts} +10 -3
- package/dist/{userDB-7fM4tpgr.d.mts → userDB-DusL7OXe.d.ts} +10 -3
- package/dist/util/packer/index.d.mts +3 -63
- package/dist/util/packer/index.d.ts +3 -63
- package/dist/util/packer/index.js +53 -1
- package/dist/util/packer/index.js.map +1 -1
- package/dist/util/packer/index.mjs +53 -1
- package/dist/util/packer/index.mjs.map +1 -1
- package/package.json +7 -4
- package/src/core/types/types-legacy.ts +13 -1
- package/src/core/types/user.ts +9 -2
- package/src/core/util/index.ts +5 -4
- package/src/impl/common/BaseUserDB.ts +33 -22
- package/src/impl/common/SyncStrategy.ts +7 -0
- package/src/impl/common/index.ts +0 -1
- package/src/impl/common/userDBHelpers.ts +4 -4
- package/src/impl/couch/CouchDBSyncStrategy.ts +10 -0
- package/src/impl/couch/adminDB.ts +1 -1
- package/src/impl/couch/courseAPI.ts +7 -6
- package/src/impl/couch/courseDB.ts +1 -1
- package/src/impl/couch/courseLookupDB.ts +1 -1
- package/src/impl/couch/index.ts +10 -5
- package/src/impl/couch/updateQueue.ts +12 -8
- package/src/impl/couch/user-course-relDB.ts +17 -27
- package/src/impl/static/NoOpSyncStrategy.ts +5 -0
- package/src/impl/static/StaticDataUnpacker.ts +18 -36
- package/src/impl/static/courseDB.ts +135 -17
- package/src/study/getCardDataShape.ts +2 -2
- package/src/util/migrator/FileSystemAdapter.ts +20 -0
- package/src/util/migrator/StaticToCouchDBMigrator.ts +6 -0
- package/src/util/packer/CouchDBToStaticPacker.ts +92 -2
package/dist/core/index.mjs
CHANGED
|
@@ -80,7 +80,7 @@ var init_logger = __esm({
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
// src/core/types/types-legacy.ts
|
|
83
|
-
var GuestUsername, log, DocType,
|
|
83
|
+
var GuestUsername, log, DocType, DocTypePrefixes;
|
|
84
84
|
var init_types_legacy = __esm({
|
|
85
85
|
"src/core/types/types-legacy.ts"() {
|
|
86
86
|
"use strict";
|
|
@@ -102,7 +102,19 @@ var init_types_legacy = __esm({
|
|
|
102
102
|
DocType2["NAVIGATION_STRATEGY"] = "NAVIGATION_STRATEGY";
|
|
103
103
|
return DocType2;
|
|
104
104
|
})(DocType || {});
|
|
105
|
-
|
|
105
|
+
DocTypePrefixes = {
|
|
106
|
+
["CARD" /* CARD */]: "c",
|
|
107
|
+
["DISPLAYABLE_DATA" /* DISPLAYABLE_DATA */]: "dd",
|
|
108
|
+
["TAG" /* TAG */]: "TAG",
|
|
109
|
+
["CARDRECORD" /* CARDRECORD */]: "cardH",
|
|
110
|
+
["SCHEDULED_CARD" /* SCHEDULED_CARD */]: "card_review_",
|
|
111
|
+
// Add other doctypes here as they get prefixed IDs
|
|
112
|
+
["DATASHAPE" /* DATASHAPE */]: "DATASHAPE",
|
|
113
|
+
["QUESTION" /* QUESTIONTYPE */]: "QUESTION",
|
|
114
|
+
["VIEW" /* VIEW */]: "VIEW",
|
|
115
|
+
["PEDAGOGY" /* PEDAGOGY */]: "PEDAGOGY",
|
|
116
|
+
["NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */]: "NAVIGATION_STRATEGY"
|
|
117
|
+
};
|
|
106
118
|
}
|
|
107
119
|
});
|
|
108
120
|
|
|
@@ -114,16 +126,16 @@ function isQuestionRecord(c) {
|
|
|
114
126
|
return c.userAnswer !== void 0;
|
|
115
127
|
}
|
|
116
128
|
function getCardHistoryID(courseID, cardID) {
|
|
117
|
-
return `${
|
|
129
|
+
return `${DocTypePrefixes["CARDRECORD" /* CARDRECORD */]}-${courseID}-${cardID}`;
|
|
118
130
|
}
|
|
119
131
|
function parseCardHistoryID(id) {
|
|
120
132
|
const split = id.split("-");
|
|
121
133
|
let error = "";
|
|
122
134
|
error += split.length === 3 ? "" : `
|
|
123
135
|
given ID has incorrect number of '-' characters`;
|
|
124
|
-
error += split[0] ===
|
|
125
|
-
given ID does not start with ${
|
|
126
|
-
if (split.length === 3 && split[0] ===
|
|
136
|
+
error += split[0] === DocTypePrefixes["CARDRECORD" /* CARDRECORD */] ? "" : `
|
|
137
|
+
given ID does not start with ${DocTypePrefixes["CARDRECORD" /* CARDRECORD */]}`;
|
|
138
|
+
if (split.length === 3 && split[0] === DocTypePrefixes["CARDRECORD" /* CARDRECORD */]) {
|
|
127
139
|
return {
|
|
128
140
|
courseID: split[1],
|
|
129
141
|
cardID: split[2]
|
|
@@ -216,11 +228,11 @@ function scheduleCardReviewLocal(userDB, review) {
|
|
|
216
228
|
const now = moment.utc();
|
|
217
229
|
logger.info(`Scheduling for review in: ${review.time.diff(now, "h") / 24} days`);
|
|
218
230
|
void userDB.put({
|
|
219
|
-
_id:
|
|
231
|
+
_id: DocTypePrefixes["SCHEDULED_CARD" /* SCHEDULED_CARD */] + review.time.format(REVIEW_TIME_FORMAT),
|
|
220
232
|
cardId: review.card_id,
|
|
221
|
-
reviewTime: review.time,
|
|
233
|
+
reviewTime: review.time.toISOString(),
|
|
222
234
|
courseId: review.course_id,
|
|
223
|
-
scheduledAt: now,
|
|
235
|
+
scheduledAt: now.toISOString(),
|
|
224
236
|
scheduledFor: review.scheduledFor,
|
|
225
237
|
schedulingAgentId: review.schedulingAgentId
|
|
226
238
|
});
|
|
@@ -236,14 +248,14 @@ async function removeScheduledCardReviewLocal(userDB, reviewDocID) {
|
|
|
236
248
|
${JSON.stringify(err)}`);
|
|
237
249
|
});
|
|
238
250
|
}
|
|
239
|
-
var
|
|
251
|
+
var REVIEW_TIME_FORMAT, log2;
|
|
240
252
|
var init_userDBHelpers = __esm({
|
|
241
253
|
"src/impl/common/userDBHelpers.ts"() {
|
|
242
254
|
"use strict";
|
|
255
|
+
init_core();
|
|
243
256
|
init_logger();
|
|
244
257
|
init_pouchdb_setup();
|
|
245
258
|
init_dataDirectory();
|
|
246
|
-
REVIEW_PREFIX = "card_review_";
|
|
247
259
|
REVIEW_TIME_FORMAT = "YYYY-MM-DD--kk:mm:ss-SSS";
|
|
248
260
|
log2 = (s) => {
|
|
249
261
|
logger.info(s);
|
|
@@ -278,7 +290,10 @@ var init_updateQueue = __esm({
|
|
|
278
290
|
_className = "UpdateQueue";
|
|
279
291
|
pendingUpdates = {};
|
|
280
292
|
inprogressUpdates = {};
|
|
281
|
-
|
|
293
|
+
readDB;
|
|
294
|
+
// Database for read operations
|
|
295
|
+
writeDB;
|
|
296
|
+
// Database for write operations (local-first)
|
|
282
297
|
update(id, update) {
|
|
283
298
|
logger.debug(`Update requested on doc: ${id}`);
|
|
284
299
|
if (this.pendingUpdates[id]) {
|
|
@@ -288,24 +303,25 @@ var init_updateQueue = __esm({
|
|
|
288
303
|
}
|
|
289
304
|
return this.applyUpdates(id);
|
|
290
305
|
}
|
|
291
|
-
constructor(
|
|
306
|
+
constructor(readDB, writeDB) {
|
|
292
307
|
super();
|
|
293
|
-
this.
|
|
308
|
+
this.readDB = readDB;
|
|
309
|
+
this.writeDB = writeDB || readDB;
|
|
294
310
|
logger.debug(`UpdateQ initialized...`);
|
|
295
|
-
void this.
|
|
311
|
+
void this.readDB.info().then((i) => {
|
|
296
312
|
logger.debug(`db info: ${JSON.stringify(i)}`);
|
|
297
313
|
});
|
|
298
314
|
}
|
|
299
315
|
async applyUpdates(id) {
|
|
300
316
|
logger.debug(`Applying updates on doc: ${id}`);
|
|
301
317
|
if (this.inprogressUpdates[id]) {
|
|
302
|
-
await this.
|
|
318
|
+
await this.readDB.info();
|
|
303
319
|
return this.applyUpdates(id);
|
|
304
320
|
} else {
|
|
305
321
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
306
322
|
this.inprogressUpdates[id] = true;
|
|
307
323
|
try {
|
|
308
|
-
let doc = await this.
|
|
324
|
+
let doc = await this.readDB.get(id);
|
|
309
325
|
logger.debug(`Retrieved doc: ${id}`);
|
|
310
326
|
while (this.pendingUpdates[id].length !== 0) {
|
|
311
327
|
const update = this.pendingUpdates[id].splice(0, 1)[0];
|
|
@@ -318,7 +334,7 @@ var init_updateQueue = __esm({
|
|
|
318
334
|
};
|
|
319
335
|
}
|
|
320
336
|
}
|
|
321
|
-
await this.
|
|
337
|
+
await this.writeDB.put(doc);
|
|
322
338
|
logger.debug(`Put doc: ${id}`);
|
|
323
339
|
if (this.pendingUpdates[id].length === 0) {
|
|
324
340
|
this.inprogressUpdates[id] = false;
|
|
@@ -344,6 +360,60 @@ var init_updateQueue = __esm({
|
|
|
344
360
|
}
|
|
345
361
|
});
|
|
346
362
|
|
|
363
|
+
// src/impl/couch/user-course-relDB.ts
|
|
364
|
+
import moment2 from "moment";
|
|
365
|
+
var UsrCrsData;
|
|
366
|
+
var init_user_course_relDB = __esm({
|
|
367
|
+
"src/impl/couch/user-course-relDB.ts"() {
|
|
368
|
+
"use strict";
|
|
369
|
+
init_logger();
|
|
370
|
+
UsrCrsData = class {
|
|
371
|
+
user;
|
|
372
|
+
_courseId;
|
|
373
|
+
constructor(user, courseId) {
|
|
374
|
+
this.user = user;
|
|
375
|
+
this._courseId = courseId;
|
|
376
|
+
}
|
|
377
|
+
async getReviewsForcast(daysCount) {
|
|
378
|
+
const time = moment2.utc().add(daysCount, "days");
|
|
379
|
+
return this.getReviewstoDate(time);
|
|
380
|
+
}
|
|
381
|
+
async getPendingReviews() {
|
|
382
|
+
const now = moment2.utc();
|
|
383
|
+
return this.getReviewstoDate(now);
|
|
384
|
+
}
|
|
385
|
+
async getScheduledReviewCount() {
|
|
386
|
+
return (await this.getPendingReviews()).length;
|
|
387
|
+
}
|
|
388
|
+
async getCourseSettings() {
|
|
389
|
+
const regDoc = await this.user.getCourseRegistrationsDoc();
|
|
390
|
+
const crsDoc = regDoc.courses.find((c) => c.courseID === this._courseId);
|
|
391
|
+
if (crsDoc && crsDoc.settings) {
|
|
392
|
+
return crsDoc.settings;
|
|
393
|
+
} else {
|
|
394
|
+
logger.warn(`no settings found during lookup on course ${this._courseId}`);
|
|
395
|
+
return {};
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
updateCourseSettings(updates) {
|
|
399
|
+
if ("updateCourseSettings" in this.user) {
|
|
400
|
+
void this.user.updateCourseSettings(this._courseId, updates);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
async getReviewstoDate(targetDate) {
|
|
404
|
+
const allReviews = await this.user.getPendingReviews(this._courseId);
|
|
405
|
+
logger.debug(
|
|
406
|
+
`Fetching ${this.user.getUsername()}'s scheduled reviews for course ${this._courseId}.`
|
|
407
|
+
);
|
|
408
|
+
return allReviews.filter((review) => {
|
|
409
|
+
const reviewTime = moment2.utc(review.reviewTime);
|
|
410
|
+
return targetDate.isAfter(reviewTime);
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
347
417
|
// src/impl/couch/clientCache.ts
|
|
348
418
|
async function GET_CACHED(k, f) {
|
|
349
419
|
if (CLIENT_CACHE[k]) {
|
|
@@ -367,10 +437,12 @@ var init_clientCache = __esm({
|
|
|
367
437
|
import { NameSpacer } from "@vue-skuilder/common";
|
|
368
438
|
import { blankCourseElo, toCourseElo } from "@vue-skuilder/common";
|
|
369
439
|
import { prepareNote55 } from "@vue-skuilder/common";
|
|
440
|
+
import { v4 as uuidv4 } from "uuid";
|
|
370
441
|
async function addNote55(courseID, codeCourse, shape, data, author, tags, uploads, elo = blankCourseElo()) {
|
|
371
442
|
const db = getCourseDB(courseID);
|
|
372
443
|
const payload = prepareNote55(courseID, codeCourse, shape, data, author, tags, uploads);
|
|
373
|
-
const
|
|
444
|
+
const _id = `${DocTypePrefixes["DISPLAYABLE_DATA" /* DISPLAYABLE_DATA */]}-${uuidv4()}`;
|
|
445
|
+
const result = await db.put({ ...payload, _id });
|
|
374
446
|
const dataShapeId = NameSpacer.getDataShapeString({
|
|
375
447
|
course: codeCourse,
|
|
376
448
|
dataShape: shape.name
|
|
@@ -441,7 +513,9 @@ async function createCard(questionViewName, courseID, dsDescriptor, noteID, tags
|
|
|
441
513
|
}
|
|
442
514
|
async function addCard(courseID, course, id_displayable_data, id_view, elo, tags, author) {
|
|
443
515
|
const db = getCourseDB(courseID);
|
|
444
|
-
const
|
|
516
|
+
const _id = `${DocTypePrefixes["CARD" /* CARD */]}-${uuidv4()}`;
|
|
517
|
+
const card = await db.put({
|
|
518
|
+
_id,
|
|
445
519
|
course,
|
|
446
520
|
id_displayable_data,
|
|
447
521
|
id_view,
|
|
@@ -1193,7 +1267,7 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1193
1267
|
});
|
|
1194
1268
|
|
|
1195
1269
|
// src/impl/couch/classroomDB.ts
|
|
1196
|
-
import
|
|
1270
|
+
import moment3 from "moment";
|
|
1197
1271
|
var CLASSROOM_CONFIG, ClassroomDBBase, StudentClassroomDB;
|
|
1198
1272
|
var init_classroomDB2 = __esm({
|
|
1199
1273
|
"src/impl/couch/classroomDB.ts"() {
|
|
@@ -1293,9 +1367,9 @@ var init_classroomDB2 = __esm({
|
|
|
1293
1367
|
}
|
|
1294
1368
|
async getNewCards() {
|
|
1295
1369
|
const activeCards = await this._user.getActiveCards();
|
|
1296
|
-
const now =
|
|
1370
|
+
const now = moment3.utc();
|
|
1297
1371
|
const assigned = await this.getAssignedContent();
|
|
1298
|
-
const due = assigned.filter((c) => now.isAfter(
|
|
1372
|
+
const due = assigned.filter((c) => now.isAfter(moment3.utc(c.activeOn, REVIEW_TIME_FORMAT2)));
|
|
1299
1373
|
logger.info(`Due content: ${JSON.stringify(due)}`);
|
|
1300
1374
|
let ret = [];
|
|
1301
1375
|
for (let i = 0; i < due.length; i++) {
|
|
@@ -1373,7 +1447,7 @@ var init_CouchDBSyncStrategy = __esm({
|
|
|
1373
1447
|
});
|
|
1374
1448
|
|
|
1375
1449
|
// src/impl/couch/index.ts
|
|
1376
|
-
import
|
|
1450
|
+
import moment4 from "moment";
|
|
1377
1451
|
import process2 from "process";
|
|
1378
1452
|
function getCourseDB2(courseID) {
|
|
1379
1453
|
return new pouchdb_setup_default(
|
|
@@ -1407,7 +1481,7 @@ function getStartAndEndKeys2(key) {
|
|
|
1407
1481
|
endkey: key + "\uFFF0"
|
|
1408
1482
|
};
|
|
1409
1483
|
}
|
|
1410
|
-
var isBrowser, GUEST_LOCAL_DB, localUserDB, pouchDBincludeCredentialsConfig,
|
|
1484
|
+
var isBrowser, GUEST_LOCAL_DB, localUserDB, pouchDBincludeCredentialsConfig, REVIEW_TIME_FORMAT2;
|
|
1411
1485
|
var init_couch = __esm({
|
|
1412
1486
|
"src/impl/couch/index.ts"() {
|
|
1413
1487
|
"use strict";
|
|
@@ -1433,78 +1507,10 @@ var init_couch = __esm({
|
|
|
1433
1507
|
return pouchdb_setup_default.fetch(url, opts);
|
|
1434
1508
|
}
|
|
1435
1509
|
};
|
|
1436
|
-
REVIEW_PREFIX2 = "card_review_";
|
|
1437
1510
|
REVIEW_TIME_FORMAT2 = "YYYY-MM-DD--kk:mm:ss-SSS";
|
|
1438
1511
|
}
|
|
1439
1512
|
});
|
|
1440
1513
|
|
|
1441
|
-
// src/impl/couch/user-course-relDB.ts
|
|
1442
|
-
import moment4 from "moment";
|
|
1443
|
-
var UsrCrsData;
|
|
1444
|
-
var init_user_course_relDB = __esm({
|
|
1445
|
-
"src/impl/couch/user-course-relDB.ts"() {
|
|
1446
|
-
"use strict";
|
|
1447
|
-
init_couch();
|
|
1448
|
-
init_courseDB();
|
|
1449
|
-
init_logger();
|
|
1450
|
-
UsrCrsData = class {
|
|
1451
|
-
user;
|
|
1452
|
-
course;
|
|
1453
|
-
_courseId;
|
|
1454
|
-
constructor(user, courseId) {
|
|
1455
|
-
this.user = user;
|
|
1456
|
-
this.course = new CourseDB(courseId, async () => this.user);
|
|
1457
|
-
this._courseId = courseId;
|
|
1458
|
-
}
|
|
1459
|
-
async getReviewsForcast(daysCount) {
|
|
1460
|
-
const time = moment4.utc().add(daysCount, "days");
|
|
1461
|
-
return this.getReviewstoDate(time);
|
|
1462
|
-
}
|
|
1463
|
-
async getPendingReviews() {
|
|
1464
|
-
const now = moment4.utc();
|
|
1465
|
-
return this.getReviewstoDate(now);
|
|
1466
|
-
}
|
|
1467
|
-
async getScheduledReviewCount() {
|
|
1468
|
-
return (await this.getPendingReviews()).length;
|
|
1469
|
-
}
|
|
1470
|
-
async getCourseSettings() {
|
|
1471
|
-
const regDoc = await this.user.getCourseRegistrationsDoc();
|
|
1472
|
-
const crsDoc = regDoc.courses.find((c) => c.courseID === this._courseId);
|
|
1473
|
-
if (crsDoc && crsDoc.settings) {
|
|
1474
|
-
return crsDoc.settings;
|
|
1475
|
-
} else {
|
|
1476
|
-
logger.warn(`no settings found during lookup on course ${this._courseId}`);
|
|
1477
|
-
return {};
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
updateCourseSettings(updates) {
|
|
1481
|
-
void this.user.updateCourseSettings(this._courseId, updates);
|
|
1482
|
-
}
|
|
1483
|
-
async getReviewstoDate(targetDate) {
|
|
1484
|
-
const keys = getStartAndEndKeys2(REVIEW_PREFIX2);
|
|
1485
|
-
const reviews = await this.user.remote().allDocs({
|
|
1486
|
-
startkey: keys.startkey,
|
|
1487
|
-
endkey: keys.endkey,
|
|
1488
|
-
include_docs: true
|
|
1489
|
-
});
|
|
1490
|
-
logger.debug(
|
|
1491
|
-
`Fetching ${this.user.getUsername()}'s scheduled reviews for course ${this._courseId}.`
|
|
1492
|
-
);
|
|
1493
|
-
return reviews.rows.filter((r) => {
|
|
1494
|
-
if (r.id.startsWith(REVIEW_PREFIX2)) {
|
|
1495
|
-
const date = moment4.utc(r.id.substr(REVIEW_PREFIX2.length), REVIEW_TIME_FORMAT2);
|
|
1496
|
-
if (targetDate.isAfter(date)) {
|
|
1497
|
-
if (this._courseId === void 0 || r.doc.courseId === this._courseId) {
|
|
1498
|
-
return true;
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
}).map((r) => r.doc);
|
|
1503
|
-
}
|
|
1504
|
-
};
|
|
1505
|
-
}
|
|
1506
|
-
});
|
|
1507
|
-
|
|
1508
1514
|
// src/impl/common/BaseUserDB.ts
|
|
1509
1515
|
import { Status as Status3 } from "@vue-skuilder/common";
|
|
1510
1516
|
import moment5 from "moment";
|
|
@@ -1600,10 +1606,11 @@ async function dropUserFromClassroom(user, classID) {
|
|
|
1600
1606
|
async function getUserClassrooms(user) {
|
|
1601
1607
|
return getOrCreateClassroomRegistrationsDoc(user);
|
|
1602
1608
|
}
|
|
1603
|
-
var log3,
|
|
1609
|
+
var log3, BaseUser, userCoursesDoc, userClassroomsDoc;
|
|
1604
1610
|
var init_BaseUserDB = __esm({
|
|
1605
1611
|
"src/impl/common/BaseUserDB.ts"() {
|
|
1606
1612
|
"use strict";
|
|
1613
|
+
init_core();
|
|
1607
1614
|
init_util();
|
|
1608
1615
|
init_types_legacy();
|
|
1609
1616
|
init_logger();
|
|
@@ -1614,7 +1621,6 @@ var init_BaseUserDB = __esm({
|
|
|
1614
1621
|
log3 = (s) => {
|
|
1615
1622
|
logger.info(s);
|
|
1616
1623
|
};
|
|
1617
|
-
cardHistoryPrefix2 = "cardH-";
|
|
1618
1624
|
BaseUser = class _BaseUser {
|
|
1619
1625
|
static _instance;
|
|
1620
1626
|
static _initialized = false;
|
|
@@ -1635,11 +1641,13 @@ var init_BaseUserDB = __esm({
|
|
|
1635
1641
|
isLoggedIn() {
|
|
1636
1642
|
return !this._username.startsWith(GuestUsername);
|
|
1637
1643
|
}
|
|
1638
|
-
remoteDB;
|
|
1639
1644
|
remote() {
|
|
1640
1645
|
return this.remoteDB;
|
|
1641
1646
|
}
|
|
1642
1647
|
localDB;
|
|
1648
|
+
remoteDB;
|
|
1649
|
+
writeDB;
|
|
1650
|
+
// Database to use for write operations (local-first approach)
|
|
1643
1651
|
updateQueue;
|
|
1644
1652
|
async createAccount(username, password) {
|
|
1645
1653
|
if (!this.syncStrategy.canCreateAccount()) {
|
|
@@ -1703,8 +1711,8 @@ Currently logged-in as ${this._username}.`
|
|
|
1703
1711
|
const allDocs = await localDB.allDocs({ include_docs: false });
|
|
1704
1712
|
const docsToDelete = allDocs.rows.filter((row) => {
|
|
1705
1713
|
const id = row.id;
|
|
1706
|
-
return id.startsWith(
|
|
1707
|
-
id.startsWith(
|
|
1714
|
+
return id.startsWith(DocTypePrefixes["CARDRECORD" /* CARDRECORD */]) || // Card interaction history
|
|
1715
|
+
id.startsWith(DocTypePrefixes["SCHEDULED_CARD" /* SCHEDULED_CARD */]) || // Scheduled reviews
|
|
1708
1716
|
id === _BaseUser.DOC_IDS.COURSE_REGISTRATIONS || // Course registrations
|
|
1709
1717
|
id === _BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS || // Classroom registrations
|
|
1710
1718
|
id === _BaseUser.DOC_IDS.CONFIG;
|
|
@@ -1773,7 +1781,7 @@ Currently logged-in as ${this._username}.`
|
|
|
1773
1781
|
*
|
|
1774
1782
|
*/
|
|
1775
1783
|
async getActiveCards() {
|
|
1776
|
-
const keys = getStartAndEndKeys(
|
|
1784
|
+
const keys = getStartAndEndKeys(DocTypePrefixes["SCHEDULED_CARD" /* SCHEDULED_CARD */]);
|
|
1777
1785
|
const reviews = await this.remoteDB.allDocs({
|
|
1778
1786
|
startkey: keys.startkey,
|
|
1779
1787
|
endkey: keys.endkey,
|
|
@@ -1845,7 +1853,7 @@ Currently logged-in as ${this._username}.`
|
|
|
1845
1853
|
}
|
|
1846
1854
|
}
|
|
1847
1855
|
async getReviewstoDate(targetDate, course_id) {
|
|
1848
|
-
const keys = getStartAndEndKeys(
|
|
1856
|
+
const keys = getStartAndEndKeys(DocTypePrefixes["SCHEDULED_CARD" /* SCHEDULED_CARD */]);
|
|
1849
1857
|
const reviews = await this.remoteDB.allDocs({
|
|
1850
1858
|
startkey: keys.startkey,
|
|
1851
1859
|
endkey: keys.endkey,
|
|
@@ -1855,8 +1863,11 @@ Currently logged-in as ${this._username}.`
|
|
|
1855
1863
|
`Fetching ${this._username}'s scheduled reviews${course_id ? ` for course ${course_id}` : ""}.`
|
|
1856
1864
|
);
|
|
1857
1865
|
return reviews.rows.filter((r) => {
|
|
1858
|
-
if (r.id.startsWith(
|
|
1859
|
-
const date = moment5.utc(
|
|
1866
|
+
if (r.id.startsWith(DocTypePrefixes["SCHEDULED_CARD" /* SCHEDULED_CARD */])) {
|
|
1867
|
+
const date = moment5.utc(
|
|
1868
|
+
r.id.substr(DocTypePrefixes["SCHEDULED_CARD" /* SCHEDULED_CARD */].length),
|
|
1869
|
+
REVIEW_TIME_FORMAT
|
|
1870
|
+
);
|
|
1860
1871
|
if (targetDate.isAfter(date)) {
|
|
1861
1872
|
if (course_id === void 0 || r.doc.courseId === course_id) {
|
|
1862
1873
|
return true;
|
|
@@ -1971,7 +1982,8 @@ Currently logged-in as ${this._username}.`
|
|
|
1971
1982
|
const defaultConfig = {
|
|
1972
1983
|
_id: _BaseUser.DOC_IDS.CONFIG,
|
|
1973
1984
|
darkMode: false,
|
|
1974
|
-
likesConfetti: false
|
|
1985
|
+
likesConfetti: false,
|
|
1986
|
+
sessionTimeLimit: 5
|
|
1975
1987
|
};
|
|
1976
1988
|
try {
|
|
1977
1989
|
const cfg = await this.localDB.get(_BaseUser.DOC_IDS.CONFIG);
|
|
@@ -2044,7 +2056,8 @@ Currently logged-in as ${this._username}.`
|
|
|
2044
2056
|
setDBandQ() {
|
|
2045
2057
|
this.localDB = getLocalUserDB(this._username);
|
|
2046
2058
|
this.remoteDB = this.syncStrategy.setupRemoteDB(this._username);
|
|
2047
|
-
this.
|
|
2059
|
+
this.writeDB = this.syncStrategy.getWriteDB ? this.syncStrategy.getWriteDB(this._username) : this.localDB;
|
|
2060
|
+
this.updateQueue = new UpdateQueue(this.localDB, this.writeDB);
|
|
2048
2061
|
}
|
|
2049
2062
|
async init() {
|
|
2050
2063
|
_BaseUser._initialized = false;
|
|
@@ -2162,8 +2175,8 @@ Currently logged-in as ${this._username}.`
|
|
|
2162
2175
|
streak: 0,
|
|
2163
2176
|
bestInterval: 0
|
|
2164
2177
|
};
|
|
2165
|
-
|
|
2166
|
-
return initCardHistory;
|
|
2178
|
+
const putResult = await this.writeDB.put(initCardHistory);
|
|
2179
|
+
return { ...initCardHistory, _rev: putResult.rev };
|
|
2167
2180
|
} else {
|
|
2168
2181
|
throw new Error(`putCardRecord failed because of:
|
|
2169
2182
|
name:${reason.name}
|
|
@@ -2198,7 +2211,7 @@ Currently logged-in as ${this._username}.`
|
|
|
2198
2211
|
const deletePromises = duplicateDocIds.map(async (docId) => {
|
|
2199
2212
|
try {
|
|
2200
2213
|
const doc = await this.remoteDB.get(docId);
|
|
2201
|
-
await this.
|
|
2214
|
+
await this.writeDB.remove(doc);
|
|
2202
2215
|
log3(`Successfully removed duplicate review: ${docId}`);
|
|
2203
2216
|
} catch (error) {
|
|
2204
2217
|
log3(`Failed to remove duplicate review ${docId}: ${error}`);
|
|
@@ -2220,7 +2233,7 @@ Currently logged-in as ${this._username}.`
|
|
|
2220
2233
|
* @param course_id optional specification of individual course
|
|
2221
2234
|
*/
|
|
2222
2235
|
async getSeenCards(course_id) {
|
|
2223
|
-
let prefix =
|
|
2236
|
+
let prefix = DocTypePrefixes["CARDRECORD" /* CARDRECORD */];
|
|
2224
2237
|
if (course_id) {
|
|
2225
2238
|
prefix += course_id;
|
|
2226
2239
|
}
|
|
@@ -2229,8 +2242,8 @@ Currently logged-in as ${this._username}.`
|
|
|
2229
2242
|
});
|
|
2230
2243
|
const ret = [];
|
|
2231
2244
|
docs.rows.forEach((row) => {
|
|
2232
|
-
if (row.id.startsWith(
|
|
2233
|
-
ret.push(row.id.substr(
|
|
2245
|
+
if (row.id.startsWith(DocTypePrefixes["CARDRECORD" /* CARDRECORD */])) {
|
|
2246
|
+
ret.push(row.id.substr(DocTypePrefixes["CARDRECORD" /* CARDRECORD */].length));
|
|
2234
2247
|
}
|
|
2235
2248
|
});
|
|
2236
2249
|
return ret;
|
|
@@ -2242,7 +2255,7 @@ Currently logged-in as ${this._username}.`
|
|
|
2242
2255
|
async getHistory() {
|
|
2243
2256
|
const cards = await filterAllDocsByPrefix(
|
|
2244
2257
|
this.remoteDB,
|
|
2245
|
-
|
|
2258
|
+
DocTypePrefixes["CARDRECORD" /* CARDRECORD */],
|
|
2246
2259
|
{
|
|
2247
2260
|
include_docs: true,
|
|
2248
2261
|
attachments: false
|
|
@@ -2283,7 +2296,7 @@ Currently logged-in as ${this._username}.`
|
|
|
2283
2296
|
} catch (e) {
|
|
2284
2297
|
const err = e;
|
|
2285
2298
|
if (err.status === 404) {
|
|
2286
|
-
await this.
|
|
2299
|
+
await this.writeDB.put({
|
|
2287
2300
|
_id: _BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS,
|
|
2288
2301
|
registrations: []
|
|
2289
2302
|
});
|
|
@@ -2331,10 +2344,10 @@ Currently logged-in as ${this._username}.`
|
|
|
2331
2344
|
}
|
|
2332
2345
|
}
|
|
2333
2346
|
async scheduleCardReview(review) {
|
|
2334
|
-
return scheduleCardReviewLocal(this.
|
|
2347
|
+
return scheduleCardReviewLocal(this.writeDB, review);
|
|
2335
2348
|
}
|
|
2336
2349
|
async removeScheduledCardReview(reviewId) {
|
|
2337
|
-
return removeScheduledCardReviewLocal(this.
|
|
2350
|
+
return removeScheduledCardReviewLocal(this.writeDB, reviewId);
|
|
2338
2351
|
}
|
|
2339
2352
|
async registerForClassroom(_classId, _registerAs) {
|
|
2340
2353
|
return registerUserForClassroom(this._username, _classId, _registerAs);
|
|
@@ -2598,11 +2611,11 @@ init_core();
|
|
|
2598
2611
|
export {
|
|
2599
2612
|
ContentNavigator,
|
|
2600
2613
|
DocType,
|
|
2614
|
+
DocTypePrefixes,
|
|
2601
2615
|
GuestUsername,
|
|
2602
2616
|
Loggable,
|
|
2603
2617
|
Navigators,
|
|
2604
2618
|
areQuestionRecords,
|
|
2605
|
-
cardHistoryPrefix,
|
|
2606
2619
|
docIsDeleted,
|
|
2607
2620
|
getCardHistoryID,
|
|
2608
2621
|
getStudySource,
|