@vue-skuilder/db 0.1.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.
Files changed (62) hide show
  1. package/README.md +26 -0
  2. package/dist/core/index.d.mts +3 -0
  3. package/dist/core/index.d.ts +3 -0
  4. package/dist/core/index.js +7906 -0
  5. package/dist/core/index.js.map +1 -0
  6. package/dist/core/index.mjs +7886 -0
  7. package/dist/core/index.mjs.map +1 -0
  8. package/dist/index-QMtzQI65.d.mts +734 -0
  9. package/dist/index-QMtzQI65.d.ts +734 -0
  10. package/dist/index.d.mts +133 -0
  11. package/dist/index.d.ts +133 -0
  12. package/dist/index.js +8726 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/index.mjs +8699 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/eslint.config.mjs +20 -0
  17. package/package.json +47 -0
  18. package/src/core/bulkImport/cardProcessor.ts +165 -0
  19. package/src/core/bulkImport/index.ts +2 -0
  20. package/src/core/bulkImport/types.ts +27 -0
  21. package/src/core/index.ts +9 -0
  22. package/src/core/interfaces/adminDB.ts +27 -0
  23. package/src/core/interfaces/classroomDB.ts +75 -0
  24. package/src/core/interfaces/contentSource.ts +64 -0
  25. package/src/core/interfaces/courseDB.ts +139 -0
  26. package/src/core/interfaces/dataLayerProvider.ts +46 -0
  27. package/src/core/interfaces/index.ts +7 -0
  28. package/src/core/interfaces/navigationStrategyManager.ts +46 -0
  29. package/src/core/interfaces/userDB.ts +183 -0
  30. package/src/core/navigators/elo.ts +76 -0
  31. package/src/core/navigators/index.ts +57 -0
  32. package/src/core/readme.md +9 -0
  33. package/src/core/types/contentNavigationStrategy.ts +21 -0
  34. package/src/core/types/db.ts +7 -0
  35. package/src/core/types/types-legacy.ts +155 -0
  36. package/src/core/types/user.ts +70 -0
  37. package/src/core/util/index.ts +42 -0
  38. package/src/factory.ts +86 -0
  39. package/src/impl/pouch/PouchDataLayerProvider.ts +102 -0
  40. package/src/impl/pouch/adminDB.ts +91 -0
  41. package/src/impl/pouch/auth.ts +48 -0
  42. package/src/impl/pouch/classroomDB.ts +306 -0
  43. package/src/impl/pouch/clientCache.ts +19 -0
  44. package/src/impl/pouch/courseAPI.ts +245 -0
  45. package/src/impl/pouch/courseDB.ts +772 -0
  46. package/src/impl/pouch/courseLookupDB.ts +135 -0
  47. package/src/impl/pouch/index.ts +235 -0
  48. package/src/impl/pouch/pouchdb-setup.ts +16 -0
  49. package/src/impl/pouch/types.ts +7 -0
  50. package/src/impl/pouch/updateQueue.ts +89 -0
  51. package/src/impl/pouch/user-course-relDB.ts +73 -0
  52. package/src/impl/pouch/userDB.ts +1097 -0
  53. package/src/index.ts +8 -0
  54. package/src/study/SessionController.ts +401 -0
  55. package/src/study/SpacedRepetition.ts +128 -0
  56. package/src/study/getCardDataShape.ts +34 -0
  57. package/src/study/index.ts +2 -0
  58. package/src/util/Loggable.ts +11 -0
  59. package/src/util/index.ts +1 -0
  60. package/src/util/logger.ts +55 -0
  61. package/tsconfig.json +12 -0
  62. package/tsup.config.ts +17 -0
@@ -0,0 +1,20 @@
1
+ import backendConfig from '../../eslint.config.backend.mjs';
2
+
3
+ export default [
4
+ ...backendConfig,
5
+ {
6
+ ignores: ['node_modules/**', 'dist/**', 'eslint.config.mjs', 'tsup.config.ts'],
7
+ },
8
+ {
9
+ languageOptions: {
10
+ parserOptions: {
11
+ project: './tsconfig.json',
12
+ tsconfigRootDir: import.meta.dirname,
13
+ },
14
+ },
15
+ rules: {
16
+ // Database-specific rules
17
+ '@typescript-eslint/no-explicit-any': 'off', // PouchDB types often use any
18
+ },
19
+ },
20
+ ];
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@vue-skuilder/db",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.1.1",
7
+ "description": "Database layer for vue-skuilder",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js"
16
+ },
17
+ "./core": {
18
+ "types": "./dist/core/index.d.ts",
19
+ "import": "./dist/core/index.mjs",
20
+ "require": "./dist/core/index.js"
21
+ },
22
+ "./pouch": {
23
+ "types": "./dist/pouch/index.d.ts",
24
+ "import": "./dist/pouch/index.mjs",
25
+ "require": "./dist/pouch/index.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "build": "tsup",
30
+ "build:debug": "tsup --sourcemap inline",
31
+ "dev": "tsup --watch",
32
+ "lint": "npx eslint .",
33
+ "lint:fix": "npx eslint . --fix",
34
+ "lint:check": "npx eslint . --max-warnings 0"
35
+ },
36
+ "dependencies": {
37
+ "@nilock2/pouchdb-authentication": "^1.0.2",
38
+ "@vue-skuilder/common": "workspace:*",
39
+ "moment": "^2.29.4",
40
+ "pouchdb": "^9.0.0",
41
+ "pouchdb-find": "^9.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "tsup": "^8.0.2",
45
+ "typescript": "~5.7.2"
46
+ }
47
+ }
@@ -0,0 +1,165 @@
1
+ import { CourseElo, Status, ParsedCard, BulkImportCardData } from '@vue-skuilder/common';
2
+ import { CourseDBInterface } from '../../core/interfaces/courseDB';
3
+ import { ImportResult, BulkCardProcessorConfig } from './types';
4
+ import { logger } from '../../util/logger';
5
+
6
+ /**
7
+ * Processes multiple cards from bulk text input
8
+ *
9
+ * @param parsedCards - Array of parsed cards to import
10
+ * @param courseDB - Course database interface
11
+ * @param config - Configuration for the card processor
12
+ * @returns Array of import results
13
+ */
14
+ export async function importParsedCards(
15
+ parsedCards: ParsedCard[],
16
+ courseDB: CourseDBInterface,
17
+ config: BulkCardProcessorConfig
18
+ ): Promise<ImportResult[]> {
19
+ const results: ImportResult[] = [];
20
+
21
+ for (const parsedCard of parsedCards) {
22
+ try {
23
+ // processCard takes a ParsedCard and returns an ImportResult
24
+ const result = await processCard(parsedCard, courseDB, config);
25
+ results.push(result);
26
+ } catch (error) {
27
+ logger.error('Error processing card:', error);
28
+ // Reconstruct originalText from parsedCard for this specific catch block
29
+ // This is a fallback if processCard itself throws an unhandled error.
30
+ // Normally, processCard should return an ImportResult with status 'error'.
31
+ let errorOriginalText = parsedCard.markdown;
32
+ if (parsedCard.tags && parsedCard.tags.length > 0) {
33
+ errorOriginalText += `\ntags: ${parsedCard.tags.join(', ')}`;
34
+ }
35
+ if (parsedCard.elo !== undefined) {
36
+ errorOriginalText += `\nelo: ${parsedCard.elo}`;
37
+ }
38
+ results.push({
39
+ originalText: errorOriginalText,
40
+ status: 'error',
41
+ message: `Error processing card: ${
42
+ error instanceof Error ? error.message : 'Unknown error'
43
+ }`,
44
+ });
45
+ }
46
+ }
47
+
48
+ return results;
49
+ }
50
+
51
+ /**
52
+ * Processes a single parsed card
53
+ *
54
+ * @param parsedCard - Parsed card data
55
+ * @param courseDB - Course database interface
56
+ * @param config - Configuration for the card processor
57
+ * @returns Import result for the card
58
+ */
59
+ async function processCard(
60
+ parsedCard: ParsedCard,
61
+ courseDB: CourseDBInterface,
62
+ config: BulkCardProcessorConfig
63
+ ): Promise<ImportResult> {
64
+ const { markdown, tags, elo } = parsedCard;
65
+
66
+ // Build the original text representation including metadata
67
+ let originalText = markdown;
68
+ if (tags.length > 0) {
69
+ originalText += `\ntags: ${tags.join(', ')}`;
70
+ }
71
+ if (elo !== undefined) {
72
+ originalText += `\nelo: ${elo}`;
73
+ }
74
+
75
+ // Create card data object
76
+ const cardData: BulkImportCardData = {
77
+ Input: markdown,
78
+ Uploads: [], // No uploads for bulk import
79
+ };
80
+
81
+ const tagsElo: CourseElo['tags'] = {};
82
+ for (const tag of tags) {
83
+ tagsElo[tag] = {
84
+ score: elo || 0,
85
+ count: 1,
86
+ };
87
+ }
88
+
89
+ try {
90
+ const result = await courseDB.addNote(
91
+ config.courseCode,
92
+ config.dataShape,
93
+ cardData,
94
+ config.userName,
95
+ tags,
96
+ undefined, // attachments
97
+ elo
98
+ ? {
99
+ global: {
100
+ score: elo,
101
+ count: 1,
102
+ },
103
+ tags: tagsElo,
104
+ misc: {},
105
+ }
106
+ : undefined
107
+ );
108
+
109
+ if (result.status === Status.ok) {
110
+ return {
111
+ originalText,
112
+ status: 'success',
113
+ message: 'Card added successfully.',
114
+ cardId: result.id ? result.id : '(unknown)',
115
+ };
116
+ } else {
117
+ return {
118
+ originalText,
119
+ status: 'error',
120
+ message: result.message || 'Failed to add card to database. Unknown error.',
121
+ };
122
+ }
123
+ } catch (error) {
124
+ logger.error('Error adding note:', error);
125
+ return {
126
+ originalText,
127
+ status: 'error',
128
+ message: `Error adding card: ${error instanceof Error ? error.message : 'Unknown error'}`,
129
+ };
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Validates the configuration for bulk card processing
135
+ *
136
+ * @param config - Configuration to validate
137
+ * @returns Object with validation result and error message if any
138
+ */
139
+ export function validateProcessorConfig(config: Partial<BulkCardProcessorConfig>): {
140
+ isValid: boolean;
141
+ errorMessage?: string;
142
+ } {
143
+ if (!config.dataShape) {
144
+ return {
145
+ isValid: false,
146
+ errorMessage: 'No data shape provided for card processing',
147
+ };
148
+ }
149
+
150
+ if (!config.courseCode) {
151
+ return {
152
+ isValid: false,
153
+ errorMessage: 'No course code provided for card processing',
154
+ };
155
+ }
156
+
157
+ if (!config.userName) {
158
+ return {
159
+ isValid: false,
160
+ errorMessage: 'No user name provided for card processing',
161
+ };
162
+ }
163
+
164
+ return { isValid: true };
165
+ }
@@ -0,0 +1,2 @@
1
+ export * from './cardProcessor.js';
2
+ export * from './types.js';
@@ -0,0 +1,27 @@
1
+ import { DataShape } from '@vue-skuilder/common';
2
+
3
+ /**
4
+ * Interface representing the result of a bulk import operation for a single card
5
+ */
6
+ export interface ImportResult {
7
+ /** The original text input for the card */
8
+ originalText: string;
9
+ /** Status of the import operation */
10
+ status: 'success' | 'error';
11
+ /** Message describing the result or error */
12
+ message: string;
13
+ /** ID of the newly created card (only for success) */
14
+ cardId?: string;
15
+ }
16
+
17
+ /**
18
+ * Configuration for the bulk card processor
19
+ */
20
+ export interface BulkCardProcessorConfig {
21
+ /** The data shape to use for the cards */
22
+ dataShape: DataShape;
23
+ /** The course code used for adding notes */
24
+ courseCode: string;
25
+ /** The username of the current user */
26
+ userName: string;
27
+ }
@@ -0,0 +1,9 @@
1
+ // Export all core interfaces and types
2
+
3
+ export * from './interfaces';
4
+ export * from './types/types-legacy';
5
+ export * from './types/user';
6
+ export * from '../util/Loggable';
7
+ export * from './util';
8
+ export * from './navigators';
9
+ export * from './bulkImport';
@@ -0,0 +1,27 @@
1
+ import { ClassroomConfig, CourseConfig } from '@vue-skuilder/common';
2
+
3
+ /**
4
+ * Admin functionality
5
+ */
6
+ export interface AdminDBInterface {
7
+ /**
8
+ * Get all users
9
+ */
10
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
11
+ getUsers(): Promise<PouchDB.Core.Document<{}>[]>;
12
+
13
+ /**
14
+ * Get all courses
15
+ */
16
+ getCourses(): Promise<CourseConfig[]>;
17
+
18
+ /**
19
+ * Remove a course
20
+ */
21
+ removeCourse(id: string): Promise<PouchDB.Core.Response>;
22
+
23
+ /**
24
+ * Get all classrooms
25
+ */
26
+ getClassrooms(): Promise<(ClassroomConfig & { _id: string })[]>;
27
+ }
@@ -0,0 +1,75 @@
1
+ import { ClassroomConfig } from '@vue-skuilder/common';
2
+ import { ScheduledCard } from '../types/user';
3
+ import { StudySessionNewItem, StudySessionReviewItem } from './contentSource';
4
+
5
+ /**
6
+ * Classroom management
7
+ */
8
+ export interface ClassroomDBInterface {
9
+ /**
10
+ * Get classroom config
11
+ */
12
+ getConfig(): ClassroomConfig;
13
+
14
+ /**
15
+ * Get assigned content
16
+ */
17
+ getAssignedContent(): Promise<AssignedContent[]>;
18
+ }
19
+
20
+ export interface TeacherClassroomDBInterface extends ClassroomDBInterface {
21
+ /**
22
+ * For teacher interfaces: assign content
23
+ */
24
+ assignContent?(content: AssignedContent): Promise<boolean>;
25
+
26
+ /**
27
+ * For teacher interfaces: remove content
28
+ */
29
+ removeContent?(content: AssignedContent): Promise<void>;
30
+ }
31
+
32
+ export interface StudentClassroomDBInterface extends ClassroomDBInterface {
33
+ /**
34
+ * For student interfaces: get pending reviews
35
+ */
36
+ getPendingReviews?(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
37
+
38
+ /**
39
+ * For student interfaces: get new cards
40
+ */
41
+ getNewCards?(limit?: number): Promise<StudySessionNewItem[]>;
42
+ }
43
+
44
+ export type AssignedContent = AssignedCourse | AssignedTag | AssignedCard;
45
+
46
+ export interface AssignedTag extends ContentBase {
47
+ type: 'tag';
48
+ tagID: string;
49
+ }
50
+ export interface AssignedCourse extends ContentBase {
51
+ type: 'course';
52
+ }
53
+ export interface AssignedCard extends ContentBase {
54
+ type: 'card';
55
+ cardID: string;
56
+ }
57
+
58
+ interface ContentBase {
59
+ type: 'course' | 'tag' | 'card';
60
+ /**
61
+ * Username of the assigning teacher.
62
+ */
63
+ assignedBy: string;
64
+ /**
65
+ * Date the content was assigned.
66
+ */
67
+ assignedOn: moment.Moment;
68
+ /**
69
+ * A 'due' date for this assigned content, for scheduling content
70
+ * in advance. Content will not be actively pushed to students until
71
+ * this date.
72
+ */
73
+ activeOn: moment.Moment;
74
+ courseID: string;
75
+ }
@@ -0,0 +1,64 @@
1
+ import { UserDBInterface } from '..';
2
+ import { StudentClassroomDB } from '../../impl/pouch/classroomDB';
3
+ import { CourseDB } from '../../impl/pouch/courseDB';
4
+ import { ScheduledCard } from '@/core/types/user';
5
+
6
+ export type StudySessionFailedItem = StudySessionFailedNewItem | StudySessionFailedReviewItem;
7
+
8
+ export interface StudySessionFailedNewItem extends StudySessionItem {
9
+ status: 'failed-new';
10
+ }
11
+ export interface StudySessionFailedReviewItem extends StudySessionReviewItem {
12
+ status: 'failed-review';
13
+ }
14
+
15
+ export interface StudySessionNewItem extends StudySessionItem {
16
+ status: 'new';
17
+ }
18
+
19
+ export interface StudySessionReviewItem extends StudySessionItem {
20
+ reviewID: string;
21
+ status: 'review' | 'failed-review';
22
+ }
23
+ export function isReview(item: StudySessionItem): item is StudySessionReviewItem {
24
+ const ret = item.status === 'review' || item.status === 'failed-review' || 'reviewID' in item;
25
+
26
+ // console.log(`itemIsReview: ${ret}
27
+ // \t${JSON.stringify(item)}`);
28
+
29
+ return ret;
30
+ }
31
+
32
+ export interface StudySessionItem {
33
+ status: 'new' | 'review' | 'failed-new' | 'failed-review';
34
+ qualifiedID: `${string}-${string}` | `${string}-${string}-${number}`;
35
+ cardID: string;
36
+ contentSourceType: 'course' | 'classroom';
37
+ contentSourceID: string;
38
+ courseID: string;
39
+ // reviewID?: string;
40
+ }
41
+
42
+ export interface ContentSourceID {
43
+ type: 'course' | 'classroom';
44
+ id: string;
45
+ }
46
+
47
+ export interface StudyContentSource {
48
+ getPendingReviews(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
49
+ getNewCards(n?: number): Promise<StudySessionNewItem[]>;
50
+ }
51
+
52
+ export async function getStudySource(
53
+ source: ContentSourceID,
54
+ user: UserDBInterface
55
+ ): Promise<StudyContentSource> {
56
+ if (source.type === 'classroom') {
57
+ return await StudentClassroomDB.factory(source.id, user);
58
+ } else {
59
+ // if (source.type === 'course') - removed so tsc is certain something returns
60
+ return new CourseDB(source.id, async () => {
61
+ return user;
62
+ });
63
+ }
64
+ }
@@ -0,0 +1,139 @@
1
+ import { CourseConfig, CourseElo, DataShape, SkuilderCourseData } from '@vue-skuilder/common';
2
+ import { StudySessionNewItem, StudySessionItem } from './contentSource';
3
+ import { TagStub, Tag } from '../types/types-legacy';
4
+ import { DataLayerResult } from '../types/db';
5
+ import { NavigationStrategyManager } from './navigationStrategyManager';
6
+
7
+ /**
8
+ * Course content and management
9
+ */
10
+ export interface CoursesDBInterface {
11
+ /**
12
+ * Get course config
13
+ */
14
+ getCourseConfig(courseId: string): Promise<CourseConfig>;
15
+
16
+ /**
17
+ * Get a list of all courses
18
+ */
19
+ getCourseList(): Promise<CourseConfig[]>;
20
+
21
+ disambiguateCourse(courseId: string, disambiguator: string): Promise<void>;
22
+ }
23
+
24
+ export interface CourseInfo {
25
+ cardCount: number;
26
+ registeredUsers: number;
27
+ }
28
+
29
+ export interface CourseDBInterface extends NavigationStrategyManager {
30
+ /**
31
+ * Get course config
32
+ */
33
+ getCourseConfig(): Promise<CourseConfig>;
34
+
35
+ getCourseID(): string;
36
+
37
+ /**
38
+ * Set course config
39
+ */
40
+ updateCourseConfig(cfg: CourseConfig): Promise<PouchDB.Core.Response>;
41
+
42
+ getCourseInfo(): Promise<CourseInfo>;
43
+
44
+ getCourseDoc<T extends SkuilderCourseData>(
45
+ id: string,
46
+ options?: PouchDB.Core.GetOptions
47
+ ): Promise<T>;
48
+ getCourseDocs<T extends SkuilderCourseData>(
49
+ ids: string[],
50
+ options?: PouchDB.Core.AllDocsOptions
51
+ ): Promise<PouchDB.Core.AllDocsWithKeysResponse<{} & T>>;
52
+
53
+ /**
54
+ * Get cards sorted by ELO rating
55
+ */
56
+ getCardsByELO(elo: number, limit?: number): Promise<string[]>;
57
+
58
+ /**
59
+ * Get ELO data for specific cards
60
+ */
61
+ getCardEloData(cardIds: string[]): Promise<CourseElo[]>;
62
+
63
+ /**
64
+ * Update card ELO rating
65
+ */
66
+ updateCardElo(cardId: string, elo: CourseElo): Promise<PouchDB.Core.Response>;
67
+
68
+ /**
69
+ * Get new cards for study
70
+ */
71
+ getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
72
+
73
+ /**
74
+ * Get cards centered at a particular ELO rating
75
+ */
76
+ getCardsCenteredAtELO(
77
+ options: { limit: number; elo: 'user' | 'random' | number },
78
+ filter?: (id: string) => boolean
79
+ ): Promise<StudySessionItem[]>;
80
+
81
+ /**
82
+ * Get tags for a card
83
+ */
84
+ getAppliedTags(cardId: string): Promise<PouchDB.Query.Response<TagStub>>;
85
+
86
+ /**
87
+ * Add a tag to a card
88
+ */
89
+ addTagToCard(cardId: string, tagId: string, updateELO?: boolean): Promise<PouchDB.Core.Response>;
90
+
91
+ /**
92
+ * Remove a tag from a card
93
+ */
94
+ removeTagFromCard(cardId: string, tagId: string): Promise<PouchDB.Core.Response>;
95
+
96
+ /**
97
+ * Create a new tag
98
+ */
99
+ createTag(tagName: string): Promise<PouchDB.Core.Response>;
100
+
101
+ /**
102
+ * Get a tag by name
103
+ */
104
+ getTag(tagName: string): Promise<Tag>;
105
+
106
+ /**
107
+ * Update a tag
108
+ */
109
+ updateTag(tag: Tag): Promise<PouchDB.Core.Response>;
110
+
111
+ /**
112
+ * Get all tag stubs for a course
113
+ */
114
+ getCourseTagStubs(): Promise<PouchDB.Core.AllDocsResponse<Tag>>;
115
+
116
+ /**
117
+ * Add a note to the course
118
+ */
119
+ addNote(
120
+ codeCourse: string,
121
+ shape: DataShape,
122
+ data: unknown,
123
+ author: string,
124
+ tags: string[],
125
+ uploads?: { [key: string]: PouchDB.Core.FullAttachment },
126
+ elo?: CourseElo
127
+ ): Promise<DataLayerResult>;
128
+
129
+ removeCard(cardId: string): Promise<PouchDB.Core.Response>;
130
+
131
+ getInexperiencedCards(): Promise<
132
+ {
133
+ courseId: string;
134
+ cardId: string;
135
+ count: number;
136
+ elo: CourseElo;
137
+ }[]
138
+ >;
139
+ }
@@ -0,0 +1,46 @@
1
+ // db/src/core/interfaces.ts
2
+
3
+ import { UserDBInterface } from './userDB';
4
+ import { CourseDBInterface, CoursesDBInterface } from './courseDB';
5
+ import { ClassroomDBInterface } from './classroomDB';
6
+ import { AdminDBInterface } from './adminDB';
7
+
8
+ /**
9
+ * Main factory interface for data access
10
+ */
11
+ export interface DataLayerProvider {
12
+ /**
13
+ * Get the user database interface
14
+ */
15
+ getUserDB(): UserDBInterface;
16
+
17
+ /**
18
+ * Get a course database interface
19
+ */
20
+ getCourseDB(courseId: string): CourseDBInterface;
21
+
22
+ /**
23
+ * Get the courses-lookup interface
24
+ */
25
+ getCoursesDB(): CoursesDBInterface;
26
+
27
+ /**
28
+ * Get a classroom database interface
29
+ */
30
+ getClassroomDB(classId: string, type: 'student' | 'teacher'): Promise<ClassroomDBInterface>;
31
+
32
+ /**
33
+ * Get the admin database interface
34
+ */
35
+ getAdminDB(): AdminDBInterface;
36
+
37
+ /**
38
+ * Initialize the data layer
39
+ */
40
+ initialize(): Promise<void>;
41
+
42
+ /**
43
+ * Teardown the data layer
44
+ */
45
+ teardown(): Promise<void>;
46
+ }
@@ -0,0 +1,7 @@
1
+ export * from './adminDB';
2
+ export * from './classroomDB';
3
+ export * from './contentSource';
4
+ export * from './courseDB';
5
+ export * from './dataLayerProvider';
6
+
7
+ export * from './userDB';
@@ -0,0 +1,46 @@
1
+ import { ContentNavigationStrategyData } from '../types/contentNavigationStrategy';
2
+
3
+ /**
4
+ * A NavigationStrategyManager is an entity which may contain multiple strategies.
5
+ *
6
+ * This interface defines strategy CRUD.
7
+ */
8
+ export interface NavigationStrategyManager {
9
+ /**
10
+ * Get the navigation strategy for a given course
11
+ * @returns The navigation strategy for the course
12
+ */
13
+ getNavigationStrategy(id: string): Promise<ContentNavigationStrategyData>;
14
+
15
+ /**
16
+ * Get all available navigation strategies
17
+ * @returns An array of all available navigation strategies
18
+ */
19
+ getAllNavigationStrategies(): Promise<ContentNavigationStrategyData[]>;
20
+
21
+ /**
22
+ * Add a new navigation strategy
23
+ * @param data The data for the new navigation strategy
24
+ * @returns A promise that resolves when the strategy has been added
25
+ */
26
+ addNavigationStrategy(data: ContentNavigationStrategyData): Promise<void>;
27
+
28
+ /**
29
+ * Update an existing navigation strategy
30
+ * @param id The ID of the navigation strategy to update
31
+ * @param data The new data for the navigation strategy
32
+ * @returns A promise that resolves when the update is complete
33
+ */
34
+ updateNavigationStrategy(id: string, data: ContentNavigationStrategyData): Promise<void>;
35
+
36
+ /**
37
+ * @returns A content navigation strategy suitable to the current context.
38
+ */
39
+ surfaceNavigationStrategy(): Promise<ContentNavigationStrategyData>;
40
+
41
+ // [ ] addons here like:
42
+ // - determining Navigation Strategy from context of current user
43
+ // - determining weighted averages of navigation strategies
44
+ // - expressing A/B testing results of 'ecosystem of strategies'
45
+ // - etc etc
46
+ }