@vue-skuilder/db 0.1.23 → 0.1.25

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 (80) hide show
  1. package/dist/{contentSource-BP9hznNV.d.ts → contentSource-BmnmvH8C.d.ts} +268 -3
  2. package/dist/{contentSource-DsJadoBU.d.cts → contentSource-DfBbaLA-.d.cts} +268 -3
  3. package/dist/core/index.d.cts +310 -6
  4. package/dist/core/index.d.ts +310 -6
  5. package/dist/core/index.js +2606 -666
  6. package/dist/core/index.js.map +1 -1
  7. package/dist/core/index.mjs +2564 -639
  8. package/dist/core/index.mjs.map +1 -1
  9. package/dist/{dataLayerProvider-CHYrQ5pB.d.cts → dataLayerProvider-BeRXVMs5.d.cts} +1 -1
  10. package/dist/{dataLayerProvider-MDTxXq2l.d.ts → dataLayerProvider-CG9GfaAY.d.ts} +1 -1
  11. package/dist/impl/couch/index.d.cts +11 -3
  12. package/dist/impl/couch/index.d.ts +11 -3
  13. package/dist/impl/couch/index.js +2336 -656
  14. package/dist/impl/couch/index.js.map +1 -1
  15. package/dist/impl/couch/index.mjs +2316 -631
  16. package/dist/impl/couch/index.mjs.map +1 -1
  17. package/dist/impl/static/index.d.cts +4 -4
  18. package/dist/impl/static/index.d.ts +4 -4
  19. package/dist/impl/static/index.js +2312 -632
  20. package/dist/impl/static/index.js.map +1 -1
  21. package/dist/impl/static/index.mjs +2315 -630
  22. package/dist/impl/static/index.mjs.map +1 -1
  23. package/dist/{index-Dj0SEgk3.d.ts → index-BWvO-_rJ.d.ts} +1 -1
  24. package/dist/{index-B_j6u5E4.d.cts → index-Ba7hYbHj.d.cts} +1 -1
  25. package/dist/index.d.cts +278 -20
  26. package/dist/index.d.ts +278 -20
  27. package/dist/index.js +3603 -720
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +3529 -674
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{types-DQaXnuoc.d.ts → types-CJrLM1Ew.d.ts} +1 -1
  32. package/dist/{types-Bn0itutr.d.cts → types-W8n-B6HG.d.cts} +1 -1
  33. package/dist/{types-legacy-DDY4N-Uq.d.cts → types-legacy-JXDxinpU.d.cts} +5 -1
  34. package/dist/{types-legacy-DDY4N-Uq.d.ts → types-legacy-JXDxinpU.d.ts} +5 -1
  35. package/dist/util/packer/index.d.cts +3 -3
  36. package/dist/util/packer/index.d.ts +3 -3
  37. package/docs/brainstorm-navigation-paradigm.md +40 -34
  38. package/docs/future-orchestration-vision.md +216 -0
  39. package/docs/navigators-architecture.md +210 -9
  40. package/docs/todo-review-urgency-adaptation.md +205 -0
  41. package/docs/todo-strategy-authoring.md +8 -6
  42. package/package.json +3 -3
  43. package/src/core/index.ts +2 -0
  44. package/src/core/interfaces/contentSource.ts +7 -0
  45. package/src/core/interfaces/userDB.ts +50 -0
  46. package/src/core/navigators/Pipeline.ts +132 -5
  47. package/src/core/navigators/PipelineAssembler.ts +21 -22
  48. package/src/core/navigators/PipelineDebugger.ts +426 -0
  49. package/src/core/navigators/filters/WeightedFilter.ts +141 -0
  50. package/src/core/navigators/filters/types.ts +4 -0
  51. package/src/core/navigators/generators/CompositeGenerator.ts +82 -19
  52. package/src/core/navigators/generators/elo.ts +14 -1
  53. package/src/core/navigators/generators/srs.ts +146 -18
  54. package/src/core/navigators/generators/types.ts +4 -0
  55. package/src/core/navigators/index.ts +203 -13
  56. package/src/core/orchestration/gradient.ts +133 -0
  57. package/src/core/orchestration/index.ts +210 -0
  58. package/src/core/orchestration/learning.ts +250 -0
  59. package/src/core/orchestration/recording.ts +92 -0
  60. package/src/core/orchestration/signal.ts +67 -0
  61. package/src/core/types/contentNavigationStrategy.ts +38 -0
  62. package/src/core/types/learningState.ts +77 -0
  63. package/src/core/types/types-legacy.ts +4 -0
  64. package/src/core/types/userOutcome.ts +51 -0
  65. package/src/courseConfigRegistration.ts +107 -0
  66. package/src/factory.ts +6 -0
  67. package/src/impl/common/BaseUserDB.ts +16 -0
  68. package/src/impl/couch/user-course-relDB.ts +12 -0
  69. package/src/study/MixerDebugger.ts +555 -0
  70. package/src/study/SessionController.ts +159 -20
  71. package/src/study/SessionDebugger.ts +442 -0
  72. package/src/study/SourceMixer.ts +36 -17
  73. package/src/study/TODO-session-scheduling.md +133 -0
  74. package/src/study/index.ts +2 -0
  75. package/src/study/services/EloService.ts +79 -4
  76. package/src/study/services/ResponseProcessor.ts +130 -72
  77. package/src/study/services/SrsService.ts +9 -0
  78. package/tests/core/navigators/Pipeline.test.ts +2 -0
  79. package/tests/core/navigators/PipelineAssembler.test.ts +4 -4
  80. package/docs/todo-evolutionary-orchestration.md +0 -310
@@ -265,6 +265,113 @@ export function registerQuestionType(
265
265
  return true;
266
266
  }
267
267
 
268
+ /**
269
+ * Remove a data shape from the course config
270
+ * @returns true if the data shape was removed, false if it wasn't found
271
+ */
272
+ export function removeDataShape(
273
+ dataShapeName: string,
274
+ courseConfig: CourseConfig
275
+ ): boolean {
276
+ const index = courseConfig.dataShapes.findIndex((ds) => ds.name === dataShapeName);
277
+
278
+ if (index === -1) {
279
+ logger.info(`DataShape '${dataShapeName}' not found in course config`);
280
+ return false;
281
+ }
282
+
283
+ // Remove the data shape
284
+ courseConfig.dataShapes.splice(index, 1);
285
+
286
+ // Also remove references from any question types
287
+ courseConfig.questionTypes.forEach((qt) => {
288
+ const dsIndex = qt.dataShapeList.indexOf(dataShapeName);
289
+ if (dsIndex !== -1) {
290
+ qt.dataShapeList.splice(dsIndex, 1);
291
+ }
292
+ });
293
+
294
+ logger.info(`Removed DataShape: ${dataShapeName}`);
295
+ return true;
296
+ }
297
+
298
+ /**
299
+ * Remove a question type from the course config
300
+ * @returns true if the question type was removed, false if it wasn't found
301
+ */
302
+ export function removeQuestionType(
303
+ questionTypeName: string,
304
+ courseConfig: CourseConfig
305
+ ): boolean {
306
+ const index = courseConfig.questionTypes.findIndex((qt) => qt.name === questionTypeName);
307
+
308
+ if (index === -1) {
309
+ logger.info(`QuestionType '${questionTypeName}' not found in course config`);
310
+ return false;
311
+ }
312
+
313
+ // Remove the question type
314
+ courseConfig.questionTypes.splice(index, 1);
315
+
316
+ // Also remove references from data shapes
317
+ courseConfig.dataShapes.forEach((ds) => {
318
+ const qtIndex = ds.questionTypes.indexOf(questionTypeName);
319
+ if (qtIndex !== -1) {
320
+ ds.questionTypes.splice(qtIndex, 1);
321
+ }
322
+ });
323
+
324
+ logger.info(`Removed QuestionType: ${questionTypeName}`);
325
+ return true;
326
+ }
327
+
328
+ /**
329
+ * Remove data shapes and question types from course config and persist to database
330
+ */
331
+ export async function removeCustomQuestionTypes(
332
+ dataShapeNames: string[],
333
+ questionTypeNames: string[],
334
+ courseConfig: CourseConfig,
335
+ courseDB: CourseDBInterface
336
+ ): Promise<{ success: boolean; removedCount: number; errorMessage?: string }> {
337
+ try {
338
+ logger.info('Beginning custom question removal');
339
+ logger.info(`Removing ${dataShapeNames.length} data shapes and ${questionTypeNames.length} question types`);
340
+
341
+ let removedCount = 0;
342
+
343
+ // Remove question types first (they reference data shapes)
344
+ for (const qtName of questionTypeNames) {
345
+ if (removeQuestionType(qtName, courseConfig)) {
346
+ removedCount++;
347
+ }
348
+ }
349
+
350
+ // Then remove data shapes
351
+ for (const dsName of dataShapeNames) {
352
+ if (removeDataShape(dsName, courseConfig)) {
353
+ removedCount++;
354
+ }
355
+ }
356
+
357
+ // Update the course config in the database
358
+ logger.info('Updating course configuration...');
359
+ const updateResult = await courseDB.updateCourseConfig(courseConfig);
360
+
361
+ if (!updateResult.ok) {
362
+ throw new Error(`Failed to update course config: ${JSON.stringify(updateResult)}`);
363
+ }
364
+
365
+ logger.info(`Custom question removal complete: ${removedCount} items removed`);
366
+
367
+ return { success: true, removedCount };
368
+ } catch (error) {
369
+ const errorMessage = error instanceof Error ? error.message : String(error);
370
+ logger.error(`Custom question removal failed: ${errorMessage}`);
371
+ return { success: false, removedCount: 0, errorMessage };
372
+ }
373
+ }
374
+
268
375
  /**
269
376
  * Register seed data for a question type
270
377
  *
package/src/factory.ts CHANGED
@@ -4,6 +4,7 @@ import { DataLayerProvider } from './core/interfaces';
4
4
  import { BaseUser } from './impl/common';
5
5
  import { logger } from './util/logger';
6
6
  import { StaticCourseManifest } from './util/packer/types';
7
+ import { initializeNavigatorRegistry } from './core/navigators';
7
8
 
8
9
  const NOT_SET = 'NOT_SET' as const;
9
10
 
@@ -50,6 +51,11 @@ export async function initializeDataLayer(config: DataLayerConfig): Promise<Data
50
51
  logger.warn('Data layer already initialized. Returning existing instance.');
51
52
  return dataLayerInstance;
52
53
  }
54
+
55
+ // Initialize the navigator registry before creating the data layer.
56
+ // This ensures all built-in navigators are available for pipeline assembly.
57
+ await initializeNavigatorRegistry();
58
+
53
59
  if (config.options.localStoragePrefix) {
54
60
  ENV.LOCAL_STORAGE_PREFIX = config.options.localStoragePrefix;
55
61
  }
@@ -20,6 +20,7 @@ import {
20
20
  } from '@db/core/types/user';
21
21
  import { DocumentUpdater } from '@db/study';
22
22
  import { CardHistory, CardRecord } from '../../core/types/types-legacy';
23
+ import { UserOutcomeRecord } from '../../core/types/userOutcome';
23
24
  import type { SyncStrategy } from './SyncStrategy';
24
25
  import {
25
26
  filterAllDocsByPrefix,
@@ -1088,6 +1089,21 @@ Currently logged-in as ${this._username}.`
1088
1089
  await this.localDB.put(doc);
1089
1090
  }
1090
1091
 
1092
+ public async putUserOutcome(record: UserOutcomeRecord): Promise<void> {
1093
+ try {
1094
+ await this.localDB.put(record);
1095
+ } catch (err: any) {
1096
+ if (err.status === 409) {
1097
+ // Overwrite if exists
1098
+ const existing = await this.localDB.get(record._id);
1099
+ (record as any)._rev = existing._rev;
1100
+ await this.localDB.put(record);
1101
+ } else {
1102
+ throw err;
1103
+ }
1104
+ }
1105
+ }
1106
+
1091
1107
  public async deleteStrategyState(courseId: string, strategyKey: string): Promise<void> {
1092
1108
  const docId = buildStrategyStateId(courseId, strategyKey);
1093
1109
  try {
@@ -52,6 +52,18 @@ export class UsrCrsData implements UsrCrsDataInterface {
52
52
  }
53
53
  }
54
54
 
55
+ public async getStrategyState<T>(strategyKey: string): Promise<T | null> {
56
+ return this.user.getStrategyState<T>(this._courseId, strategyKey);
57
+ }
58
+
59
+ public async putStrategyState<T>(strategyKey: string, data: T): Promise<void> {
60
+ return this.user.putStrategyState<T>(this._courseId, strategyKey, data);
61
+ }
62
+
63
+ public async deleteStrategyState(strategyKey: string): Promise<void> {
64
+ return this.user.deleteStrategyState(this._courseId, strategyKey);
65
+ }
66
+
55
67
  private async getReviewstoDate(targetDate: Moment) {
56
68
  // Use the interface method instead of direct database access
57
69
  const allReviews = await this.user.getPendingReviews(this._courseId);