@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.
- 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 +825 -762
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +812 -750
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-BZmLyBVw.d.mts → dataLayerProvider-BInqI_RF.d.mts} +1 -1
- package/dist/{dataLayerProvider-BuntXkCs.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 +2261 -2081
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +2274 -2095
- 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 +524 -1064
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +515 -1058
- 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 +200 -9
- package/dist/index.d.ts +200 -9
- package/dist/index.js +4123 -2820
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4119 -2830
- package/dist/index.mjs.map +1 -1
- package/dist/{types-D6SnlHPm.d.ts → types-BefDGkKa.d.ts} +1 -1
- package/dist/{types-DPRvCrIk.d.mts → types-DC-ckZug.d.mts} +1 -1
- package/dist/{types-legacy-WPe8CtO-.d.mts → types-legacy-Birv-Jx6.d.mts} +2 -2
- package/dist/{types-legacy-WPe8CtO-.d.ts → types-legacy-Birv-Jx6.d.ts} +2 -2
- package/dist/{userDB-D9EuWTp1.d.ts → userDB-C33Hzjgn.d.mts} +11 -4
- package/dist/{userDB-31gsvxyd.d.mts → userDB-DusL7OXe.d.ts} +11 -4
- 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/factory.ts +25 -0
- package/src/impl/common/BaseUserDB.ts +62 -28
- package/src/impl/common/SyncStrategy.ts +7 -0
- package/src/impl/common/index.ts +0 -1
- package/src/impl/common/userDBHelpers.ts +15 -5
- package/src/impl/couch/CouchDBSyncStrategy.ts +10 -0
- package/src/impl/couch/courseAPI.ts +7 -6
- package/src/impl/couch/courseLookupDB.ts +24 -0
- 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/util/dataDirectory.test.ts +53 -0
- package/src/util/dataDirectory.ts +52 -0
- package/src/util/index.ts +3 -0
- package/src/util/migrator/FileSystemAdapter.ts +79 -0
- package/src/util/migrator/StaticToCouchDBMigrator.ts +713 -0
- package/src/util/migrator/index.ts +18 -0
- package/src/util/migrator/types.ts +84 -0
- package/src/util/migrator/validation.ts +517 -0
- package/src/util/packer/CouchDBToStaticPacker.ts +92 -2
- 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
|
|
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
|
+
};
|