@vue-skuilder/db 0.1.6 → 0.1.8-0

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 (70) hide show
  1. package/dist/{SyncStrategy-DnJRj-Xp.d.mts → SyncStrategy-CyATpyLQ.d.mts} +6 -0
  2. package/dist/{SyncStrategy-DnJRj-Xp.d.ts → SyncStrategy-CyATpyLQ.d.ts} +6 -0
  3. package/dist/core/index.d.mts +5 -5
  4. package/dist/core/index.d.ts +5 -5
  5. package/dist/core/index.js +825 -762
  6. package/dist/core/index.js.map +1 -1
  7. package/dist/core/index.mjs +812 -750
  8. package/dist/core/index.mjs.map +1 -1
  9. package/dist/{dataLayerProvider-BZmLyBVw.d.mts → dataLayerProvider-BInqI_RF.d.mts} +1 -1
  10. package/dist/{dataLayerProvider-BuntXkCs.d.ts → dataLayerProvider-DqtNroSh.d.ts} +1 -1
  11. package/dist/impl/couch/index.d.mts +6 -6
  12. package/dist/impl/couch/index.d.ts +6 -6
  13. package/dist/impl/couch/index.js +2261 -2081
  14. package/dist/impl/couch/index.js.map +1 -1
  15. package/dist/impl/couch/index.mjs +2274 -2095
  16. package/dist/impl/couch/index.mjs.map +1 -1
  17. package/dist/impl/static/index.d.mts +8 -6
  18. package/dist/impl/static/index.d.ts +8 -6
  19. package/dist/impl/static/index.js +524 -1064
  20. package/dist/impl/static/index.js.map +1 -1
  21. package/dist/impl/static/index.mjs +515 -1058
  22. package/dist/impl/static/index.mjs.map +1 -1
  23. package/dist/index-CLL31bEy.d.ts +137 -0
  24. package/dist/index-CUNnL38E.d.mts +137 -0
  25. package/dist/index.d.mts +200 -9
  26. package/dist/index.d.ts +200 -9
  27. package/dist/index.js +4123 -2820
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +4119 -2830
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{types-D6SnlHPm.d.ts → types-BefDGkKa.d.ts} +1 -1
  32. package/dist/{types-DPRvCrIk.d.mts → types-DC-ckZug.d.mts} +1 -1
  33. package/dist/{types-legacy-WPe8CtO-.d.mts → types-legacy-Birv-Jx6.d.mts} +2 -2
  34. package/dist/{types-legacy-WPe8CtO-.d.ts → types-legacy-Birv-Jx6.d.ts} +2 -2
  35. package/dist/{userDB-D9EuWTp1.d.ts → userDB-C33Hzjgn.d.mts} +11 -4
  36. package/dist/{userDB-31gsvxyd.d.mts → userDB-DusL7OXe.d.ts} +11 -4
  37. package/dist/util/packer/index.d.mts +3 -63
  38. package/dist/util/packer/index.d.ts +3 -63
  39. package/dist/util/packer/index.js +53 -1
  40. package/dist/util/packer/index.js.map +1 -1
  41. package/dist/util/packer/index.mjs +53 -1
  42. package/dist/util/packer/index.mjs.map +1 -1
  43. package/package.json +7 -4
  44. package/src/core/types/types-legacy.ts +13 -1
  45. package/src/core/types/user.ts +9 -2
  46. package/src/core/util/index.ts +5 -4
  47. package/src/factory.ts +25 -0
  48. package/src/impl/common/BaseUserDB.ts +62 -28
  49. package/src/impl/common/SyncStrategy.ts +7 -0
  50. package/src/impl/common/index.ts +0 -1
  51. package/src/impl/common/userDBHelpers.ts +15 -5
  52. package/src/impl/couch/CouchDBSyncStrategy.ts +10 -0
  53. package/src/impl/couch/courseAPI.ts +7 -6
  54. package/src/impl/couch/courseLookupDB.ts +24 -0
  55. package/src/impl/couch/index.ts +10 -5
  56. package/src/impl/couch/updateQueue.ts +12 -8
  57. package/src/impl/couch/user-course-relDB.ts +17 -27
  58. package/src/impl/static/NoOpSyncStrategy.ts +5 -0
  59. package/src/impl/static/StaticDataUnpacker.ts +18 -36
  60. package/src/impl/static/courseDB.ts +135 -17
  61. package/src/util/dataDirectory.test.ts +53 -0
  62. package/src/util/dataDirectory.ts +52 -0
  63. package/src/util/index.ts +3 -0
  64. package/src/util/migrator/FileSystemAdapter.ts +79 -0
  65. package/src/util/migrator/StaticToCouchDBMigrator.ts +713 -0
  66. package/src/util/migrator/index.ts +18 -0
  67. package/src/util/migrator/types.ts +84 -0
  68. package/src/util/migrator/validation.ts +517 -0
  69. package/src/util/packer/CouchDBToStaticPacker.ts +92 -2
  70. package/src/util/tuiLogger.ts +139 -0
@@ -14,6 +14,7 @@ import {
14
14
  StaticCourseManifest,
15
15
  AttachmentData,
16
16
  } from './types';
17
+ import { FileSystemAdapter } from '../migrator/FileSystemAdapter';
17
18
 
18
19
  export class CouchDBToStaticPacker {
19
20
  private config: PackerConfig;
@@ -86,6 +87,94 @@ export class CouchDBToStaticPacker {
86
87
  };
87
88
  }
88
89
 
90
+ /**
91
+ * Pack a CouchDB course database and write the static files to disk
92
+ */
93
+ async packCourseToFiles(
94
+ sourceDB: PouchDB.Database,
95
+ courseId: string,
96
+ outputDir: string,
97
+ fsAdapter: FileSystemAdapter
98
+ ): Promise<{
99
+ manifest: StaticCourseManifest;
100
+ filesWritten: number;
101
+ attachmentsFound: number;
102
+ }> {
103
+ logger.info(`Packing course ${courseId} to files in ${outputDir}`);
104
+
105
+ // First, pack the course data
106
+ const packedData = await this.packCourse(sourceDB, courseId);
107
+
108
+ // Write the files using the FileSystemAdapter
109
+ const filesWritten = await this.writePackedDataToFiles(packedData, outputDir, fsAdapter);
110
+
111
+ return {
112
+ manifest: packedData.manifest,
113
+ filesWritten,
114
+ attachmentsFound: packedData.attachments ? packedData.attachments.size : 0,
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Write packed course data to files using FileSystemAdapter
120
+ */
121
+ private async writePackedDataToFiles(
122
+ packedData: PackedCourseData,
123
+ outputDir: string,
124
+ fsAdapter: FileSystemAdapter
125
+ ): Promise<number> {
126
+ let totalFiles = 0;
127
+
128
+ // Ensure output directory exists
129
+ await fsAdapter.ensureDir(outputDir);
130
+
131
+ // Write manifest
132
+ const manifestPath = fsAdapter.joinPath(outputDir, 'manifest.json');
133
+ await fsAdapter.writeJson(manifestPath, packedData.manifest, { spaces: 2 });
134
+ totalFiles++;
135
+ logger.info(`Wrote manifest: ${manifestPath}`);
136
+
137
+ // Create subdirectories
138
+ const chunksDir = fsAdapter.joinPath(outputDir, 'chunks');
139
+ const indicesDir = fsAdapter.joinPath(outputDir, 'indices');
140
+ await fsAdapter.ensureDir(chunksDir);
141
+ await fsAdapter.ensureDir(indicesDir);
142
+
143
+ // Write chunks
144
+ for (const [chunkId, chunkData] of packedData.chunks) {
145
+ const chunkPath = fsAdapter.joinPath(chunksDir, `${chunkId}.json`);
146
+ await fsAdapter.writeJson(chunkPath, chunkData);
147
+ totalFiles++;
148
+ }
149
+ logger.info(`Wrote ${packedData.chunks.size} chunk files`);
150
+
151
+ // Write indices
152
+ for (const [indexName, indexData] of packedData.indices) {
153
+ const indexPath = fsAdapter.joinPath(indicesDir, `${indexName}.json`);
154
+ await fsAdapter.writeJson(indexPath, indexData, { spaces: 2 });
155
+ totalFiles++;
156
+ }
157
+ logger.info(`Wrote ${packedData.indices.size} index files`);
158
+
159
+ // Write attachments
160
+ if (packedData.attachments && packedData.attachments.size > 0) {
161
+ for (const [attachmentPath, attachmentData] of packedData.attachments) {
162
+ const fullAttachmentPath = fsAdapter.joinPath(outputDir, attachmentPath);
163
+
164
+ // Ensure attachment directory exists
165
+ const attachmentDir = fsAdapter.dirname(fullAttachmentPath);
166
+ await fsAdapter.ensureDir(attachmentDir);
167
+
168
+ // Write binary file
169
+ await fsAdapter.writeFile(fullAttachmentPath, attachmentData.buffer);
170
+ totalFiles++;
171
+ }
172
+ logger.info(`Wrote ${packedData.attachments.size} attachment files`);
173
+ }
174
+
175
+ return totalFiles;
176
+ }
177
+
89
178
  private async extractCourseConfig(db: PouchDB.Database): Promise<CourseConfig> {
90
179
  try {
91
180
  return await db.get<CourseConfig>('CourseConfig');
@@ -322,11 +411,12 @@ export class CouchDBToStaticPacker {
322
411
 
323
412
  try {
324
413
  const designDocId = designDoc._id; // e.g., "_design/elo"
325
- const viewPath = `${designDocId}/${viewName}`;
414
+ const designDocName = designDocId.replace('_design/', ''); // Extract just "elo"
415
+ const viewPath = `${designDocName}/${viewName}`;
326
416
 
327
417
  logger.info(`Querying CouchDB view: ${viewPath}`);
328
418
 
329
- // Query the view directly from CouchDB
419
+ // Query the view directly from CouchDB using PouchDB format: "designDocName/viewName"
330
420
  const viewResults = await this.sourceDB.query(viewPath, {
331
421
  include_docs: false,
332
422
  });
@@ -0,0 +1,139 @@
1
+ // TUI-aware logging utility that redirects logs to file in Node.js
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { getAppDataDirectory } from './dataDirectory';
5
+
6
+ let logFile: string | null = null;
7
+ let isNodeEnvironment = false;
8
+
9
+ /**
10
+ * Initialize TUI logging - redirect console logs to file in Node.js
11
+ */
12
+ export function initializeTuiLogging(): void {
13
+ // Detect Node.js environment
14
+ isNodeEnvironment = typeof window === 'undefined' && typeof process !== 'undefined';
15
+
16
+ if (!isNodeEnvironment) {
17
+ return; // Browser environment - keep normal console logging
18
+ }
19
+
20
+ try {
21
+ // Set up log file path
22
+ logFile = path.join(getAppDataDirectory(), 'lastrun.log');
23
+
24
+ // Clear previous log file
25
+ if (fs.existsSync(logFile)) {
26
+ fs.unlinkSync(logFile);
27
+ }
28
+
29
+ // Create initial log entry
30
+ const startTime = new Date().toISOString();
31
+ fs.writeFileSync(logFile, `=== TUI Session Started: ${startTime} ===\n`);
32
+
33
+ // Redirect console methods to file
34
+ const originalConsole = {
35
+ // eslint-disable-next-line no-console
36
+ log: console.log,
37
+ // eslint-disable-next-line no-console
38
+ error: console.error,
39
+ // eslint-disable-next-line no-console
40
+ warn: console.warn,
41
+ // eslint-disable-next-line no-console
42
+ info: console.info
43
+ };
44
+
45
+ const writeToLog = (level: string, args: any[]) => {
46
+ const timestamp = new Date().toISOString();
47
+ const message = args.map(arg =>
48
+ typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
49
+ ).join(' ');
50
+
51
+ const logEntry = `[${timestamp}] ${level}: ${message}\n`;
52
+
53
+ try {
54
+ fs.appendFileSync(logFile!, logEntry);
55
+ } catch (err) {
56
+ // Fallback to original console if file write fails
57
+ originalConsole.error('Failed to write to log file:', err);
58
+ originalConsole[level.toLowerCase() as keyof typeof originalConsole](...args);
59
+ }
60
+ };
61
+
62
+ // Override console methods
63
+ // eslint-disable-next-line no-console
64
+ console.log = (...args) => writeToLog('INFO', args);
65
+ // eslint-disable-next-line no-console
66
+ console.info = (...args) => writeToLog('INFO', args);
67
+ // eslint-disable-next-line no-console
68
+ console.warn = (...args) => writeToLog('WARN', args);
69
+ // eslint-disable-next-line no-console
70
+ console.error = (...args) => writeToLog('ERROR', args);
71
+
72
+ // Store original methods for potential restoration
73
+ (console as any)._originalMethods = originalConsole;
74
+
75
+ // eslint-disable-next-line no-console
76
+ console.log('TUI logging initialized - logs redirected to', logFile);
77
+
78
+ } catch (err) {
79
+ // eslint-disable-next-line no-console
80
+ console.error('Failed to initialize TUI logging:', err);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Get the current log file path (for debugging)
86
+ */
87
+ export function getLogFilePath(): string | null {
88
+ return logFile;
89
+ }
90
+
91
+ /**
92
+ * Show user-facing message (always visible in TUI)
93
+ */
94
+ export function showUserMessage(message: string): void {
95
+ if (isNodeEnvironment) {
96
+ // In Node.js, write directly to stdout to bypass log redirection
97
+ process.stdout.write(message + '\n');
98
+ } else {
99
+ // In browser, use normal console
100
+ // eslint-disable-next-line no-console
101
+ console.log(message);
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Show user-facing error (always visible in TUI)
107
+ */
108
+ export function showUserError(message: string): void {
109
+ if (isNodeEnvironment) {
110
+ // In Node.js, write directly to stderr to bypass log redirection
111
+ process.stderr.write('Error: ' + message + '\n');
112
+ } else {
113
+ // In browser, use normal console
114
+ // eslint-disable-next-line no-console
115
+ console.error(message);
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Logger object with standard log levels
121
+ */
122
+ export const logger = {
123
+ debug: (message: string, ...args: any[]) => {
124
+ // eslint-disable-next-line no-console
125
+ console.log(`[DEBUG] ${message}`, ...args);
126
+ },
127
+ info: (message: string, ...args: any[]) => {
128
+ // eslint-disable-next-line no-console
129
+ console.info(`[INFO] ${message}`, ...args);
130
+ },
131
+ warn: (message: string, ...args: any[]) => {
132
+ // eslint-disable-next-line no-console
133
+ console.warn(`[WARN] ${message}`, ...args);
134
+ },
135
+ error: (message: string, ...args: any[]) => {
136
+ // eslint-disable-next-line no-console
137
+ console.error(`[ERROR] ${message}`, ...args);
138
+ },
139
+ };