documentation-hub 5.7.2
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/.eslintrc.json +43 -0
- package/.github/workflows/build.yml +64 -0
- package/.github/workflows/ci.yml +39 -0
- package/.vscode/extensions.json +3 -0
- package/Current.md +97 -0
- package/DocHub_Image.png +0 -0
- package/README.md +666 -0
- package/USER_GUIDE.md +1173 -0
- package/Updater.md +311 -0
- package/build/256x256.png +0 -0
- package/build/512x512.png +0 -0
- package/build/app-update.yml +4 -0
- package/build/create-icon.js +208 -0
- package/build/icon.ico +0 -0
- package/build/icon.png +0 -0
- package/build/icon_1024x1024.png +0 -0
- package/dist/assets/Analytics-BpsG9895.js +1 -0
- package/dist/assets/Card-IAZin8kp.js +1 -0
- package/dist/assets/CurrentSession-B-rFkHvf.js +12 -0
- package/dist/assets/Dashboard-C_5gMb0q.js +1 -0
- package/dist/assets/Documents-CqZ25axS.js +1 -0
- package/dist/assets/Input-l89xwXBi.js +1 -0
- package/dist/assets/Reporting-DqdHJY_a.js +1 -0
- package/dist/assets/Search-XNbu5z_3.js +1 -0
- package/dist/assets/SessionManager-lH9hZfzH.js +1 -0
- package/dist/assets/Sessions-ClZOPYNc.js +1 -0
- package/dist/assets/Settings-DUEHGURa.js +11 -0
- package/dist/assets/index-8xUe8ptc.js +24 -0
- package/dist/assets/index-RYyJqF7O.css +1 -0
- package/dist/assets/path-BkOl0AGO.js +1 -0
- package/dist/assets/promises-ID_B9S-h.js +1 -0
- package/dist/assets/urlHelpers-TvgahX0r.js +1 -0
- package/dist/assets/useToast-yRSO1dkm.js +1 -0
- package/dist/assets/vendor-charts-RkGK5ROP.js +36 -0
- package/dist/assets/vendor-db-l0sNRNKZ.js +1 -0
- package/dist/assets/vendor-react-BVZ_anCF.js +4 -0
- package/dist/assets/vendor-search-Dw8P0qyA.js +1 -0
- package/dist/assets/vendor-ui-BU7NfluV.js +53 -0
- package/dist/electron/PowerAutomateApiService-LfW09ZGr.js +147 -0
- package/dist/electron/main-CXkNtyv-.js +19789 -0
- package/dist/electron/main.js +5 -0
- package/dist/electron/preload.js +1 -0
- package/dist/icon.png +0 -0
- package/dist/index.html +27 -0
- package/docs/CODEBASE_ANALYSIS_REPORT.md +309 -0
- package/docs/DEBUG_LOGGING_GUIDE.md +244 -0
- package/docs/README.md +115 -0
- package/docs/TOC_WIRING_GUIDE.md +344 -0
- package/docs/analysis/Bullet_Symbol_Bug_Analysis.md +136 -0
- package/docs/analysis/DOCXMLATER_ANALYSIS_SUMMARY.txt +169 -0
- package/docs/analysis/Document_Processing_Issues_Analysis.md +704 -0
- package/docs/analysis/FIELD_PRESERVATION_ANALYSIS.md +1200 -0
- package/docs/analysis/INDENTATION_PRESERVE_ANALYSIS.md +181 -0
- package/docs/analysis/INDENTATION_PRESERVE_IMPLEMENTATION.md +207 -0
- package/docs/analysis/List_Implementation.md +206 -0
- package/docs/analysis/List_Implementation_Accuracy_Report.md +366 -0
- package/docs/analysis/PROCESSING_OPTIONS_UI_UPDATES.md +220 -0
- package/docs/analysis/RefactorStyles.md +852 -0
- package/docs/analysis/STYLE_PARAMETER_ENHANCEMENT.md +143 -0
- package/docs/analysis/docxmlater-comparison-todo-2025-11-13.md +636 -0
- package/docs/analysis/docxmlater-implementation-analysis-2025-11-13.md +340 -0
- package/docs/analysis/docxmlater-template_ui-integration-analysis.md +263 -0
- package/docs/analysis/github-issues-to-create.md +237 -0
- package/docs/api/API_README.md +538 -0
- package/docs/api/API_REFERENCE.md +751 -0
- package/docs/api/TYPE_DEFINITIONS.md +869 -0
- package/docs/architecture/FONT_EMBEDDING_GUIDE.md +318 -0
- package/docs/architecture/docxmlater-functions-and-structure.md +726 -0
- package/docs/docxmlater-readme.md +1341 -0
- package/docs/fixes/EXECUTION_LOG_TEST_BASE.md +573 -0
- package/docs/fixes/HYPERLINK_TEXT_SANITIZATION.md +253 -0
- package/docs/fixes/README.md +37 -0
- package/docs/github-issues/issue-1-body.md +125 -0
- package/docs/github-issues/issue-10-body.md +850 -0
- package/docs/github-issues/issue-2-body.md +200 -0
- package/docs/github-issues/issue-3-body.md +270 -0
- package/docs/github-issues/issue-4-body.md +169 -0
- package/docs/github-issues/issue-5-body.md +173 -0
- package/docs/github-issues/issue-6-body.md +158 -0
- package/docs/github-issues/issue-7-body.md +171 -0
- package/docs/github-issues/issue-8-body.md +407 -0
- package/docs/github-issues/issue-9-body.md +515 -0
- package/docs/github-issues/issue-tracker.md +274 -0
- package/docs/github-issues/predictive-analysis-2025-10-18.md +2131 -0
- package/docs/implementation/List_Framework_Refactor_Plan.md +336 -0
- package/docs/implementation/PRIMARY_TEXT_COLOR_FEATURE.md +217 -0
- package/docs/implementation/RELEASE_PLAN_v2.1.0.md +362 -0
- package/docs/implementation/RefactorStyles.md +588 -0
- package/docs/implementation/implement-plan.md +489 -0
- package/docs/implementation/missing-helpers-implementation.md +391 -0
- package/docs/implementation/refactor-plan.md +520 -0
- package/docs/implementation/session-implementation-complete.md +233 -0
- package/docs/implementation/session-management-plan.md +250 -0
- package/docs/setup-checklist.md +77 -0
- package/docs/versions/changelog.md +345 -0
- package/electron/customUpdater.ts +656 -0
- package/electron/main.ts +2441 -0
- package/electron/memoryConfig.ts +187 -0
- package/electron/preload.ts +394 -0
- package/electron/proxyConfig.ts +340 -0
- package/electron/services/BackupService.ts +452 -0
- package/electron/services/DictionaryService.ts +402 -0
- package/electron/services/LocalDictionaryLookupService.ts +147 -0
- package/electron/services/PowerAutomateApiService.ts +231 -0
- package/electron/services/SharePointSyncService.ts +474 -0
- package/electron/windowsCertStore.ts +427 -0
- package/electron/zscalerConfig.ts +381 -0
- package/eslint.config.js +92 -0
- package/jest.config.js +52 -0
- package/package.json +214 -0
- package/postcss.config.mjs +6 -0
- package/public/icon.png +0 -0
- package/publish-release.ps1 +5 -0
- package/renovate.json +30 -0
- package/src/App.tsx +216 -0
- package/src/__mocks__/p-limit.js +12 -0
- package/src/__mocks__/styleMock.js +1 -0
- package/src/components/common/BugReportButton.tsx +44 -0
- package/src/components/common/BugReportDialog.tsx +193 -0
- package/src/components/common/Button.tsx +153 -0
- package/src/components/common/Card.tsx +86 -0
- package/src/components/common/ColorPickerDialog.tsx +177 -0
- package/src/components/common/ConfirmDialog.tsx +96 -0
- package/src/components/common/DebugConsole.tsx +275 -0
- package/src/components/common/EmptyState.tsx +183 -0
- package/src/components/common/ErrorBoundary.tsx +98 -0
- package/src/components/common/ErrorDetailsDialog.tsx +153 -0
- package/src/components/common/ErrorFallback.tsx +218 -0
- package/src/components/common/Input.tsx +109 -0
- package/src/components/common/Skeleton.tsx +184 -0
- package/src/components/common/SplashScreen.tsx +81 -0
- package/src/components/common/Toast.tsx +155 -0
- package/src/components/common/Tooltip.tsx +79 -0
- package/src/components/common/UpdateNotification.tsx +320 -0
- package/src/components/comparison/ComparisonWindow.tsx +374 -0
- package/src/components/comparison/SideBySideDiff.tsx +486 -0
- package/src/components/comparison/index.ts +8 -0
- package/src/components/document/DocumentUploader.tsx +288 -0
- package/src/components/document/HyperlinkPreview.tsx +430 -0
- package/src/components/document/HyperlinkService.md +1484 -0
- package/src/components/document/Hyperlink_Technical_Documentation.md +496 -0
- package/src/components/document/InlineChangesView.tsx +707 -0
- package/src/components/document/ProcessingProgress.tsx +303 -0
- package/src/components/document/ProcessingResults.tsx +256 -0
- package/src/components/document/TrackedChangesDetail.tsx +530 -0
- package/src/components/document/TrackedChangesPanel.tsx +546 -0
- package/src/components/document/VirtualDocumentList.tsx +240 -0
- package/src/components/editor/DocumentEditor.tsx +723 -0
- package/src/components/editor/DocumentEditorModal.tsx +640 -0
- package/src/components/editor/EditorQuickActions.tsx +502 -0
- package/src/components/editor/EditorToolbar.tsx +312 -0
- package/src/components/editor/TableEditor.tsx +926 -0
- package/src/components/editor/index.ts +18 -0
- package/src/components/layout/Header.tsx +190 -0
- package/src/components/layout/Sidebar.tsx +313 -0
- package/src/components/layout/TitleBar.tsx +190 -0
- package/src/components/navigation/CommandPalette.tsx +233 -0
- package/src/components/navigation/KeyboardShortcutsModal.tsx +173 -0
- package/src/components/sessions/ChangeItem.tsx +408 -0
- package/src/components/sessions/ChangeViewer.tsx +1155 -0
- package/src/components/sessions/DocumentComparisonModal.tsx +314 -0
- package/src/components/sessions/ProcessingOptions.tsx +297 -0
- package/src/components/sessions/ReplacementsTab.tsx +438 -0
- package/src/components/sessions/RevisionHandlingOptions.tsx +87 -0
- package/src/components/sessions/SessionManager.tsx +188 -0
- package/src/components/sessions/StylesEditor.tsx +1335 -0
- package/src/components/sessions/TabContainer.tsx +151 -0
- package/src/components/sessions/VirtualSessionList.tsx +157 -0
- package/src/components/sessions/sessionToProcessorManager.tsx +420 -0
- package/src/components/settings/CertificateManager.tsx +410 -0
- package/src/components/settings/SegmentedControl.tsx +88 -0
- package/src/components/settings/SettingRow.tsx +52 -0
- package/src/contexts/GlobalStatsContext.tsx +396 -0
- package/src/contexts/SessionContext.tsx +2129 -0
- package/src/contexts/ThemeContext.tsx +428 -0
- package/src/contexts/UserSettingsContext.tsx +290 -0
- package/src/contexts/__tests__/GlobalStatsContext.test.tsx +390 -0
- package/src/global.d.ts +273 -0
- package/src/hooks/useDocumentQueue.tsx +210 -0
- package/src/hooks/useToast.tsx +55 -0
- package/src/main.tsx +10 -0
- package/src/pages/Analytics.tsx +386 -0
- package/src/pages/CurrentSession.tsx +1174 -0
- package/src/pages/Dashboard.tsx +319 -0
- package/src/pages/Documents.tsx +317 -0
- package/src/pages/Projects.tsx +250 -0
- package/src/pages/Reporting.tsx +386 -0
- package/src/pages/Search.tsx +349 -0
- package/src/pages/Sessions.tsx +285 -0
- package/src/pages/Settings.tsx +2662 -0
- package/src/services/HyperlinkService.ts +1085 -0
- package/src/services/document/DocXMLaterProcessor.ts +617 -0
- package/src/services/document/DocumentProcessingComparison.ts +856 -0
- package/src/services/document/DocumentSnapshotService.ts +575 -0
- package/src/services/document/WordDocumentProcessor.ts +10509 -0
- package/src/services/document/__tests__/DocXMLaterProcessor.hyperlinks.test.md +311 -0
- package/src/services/document/__tests__/WordDocumentProcessor.integration.test.ts +515 -0
- package/src/services/document/__tests__/WordDocumentProcessor.test.ts +812 -0
- package/src/services/document/blanklines/BlankLineManager.ts +658 -0
- package/src/services/document/blanklines/__tests__/paragraphChecks.test.ts +281 -0
- package/src/services/document/blanklines/helpers/blankLineInsertion.ts +87 -0
- package/src/services/document/blanklines/helpers/blankLineSnapshot.ts +251 -0
- package/src/services/document/blanklines/helpers/clearCustom.ts +121 -0
- package/src/services/document/blanklines/helpers/contextChecks.ts +117 -0
- package/src/services/document/blanklines/helpers/imageChecks.ts +51 -0
- package/src/services/document/blanklines/helpers/paragraphChecks.ts +236 -0
- package/src/services/document/blanklines/helpers/removeBlanksBetweenListItems.ts +91 -0
- package/src/services/document/blanklines/helpers/removeTrailingBlanks.ts +35 -0
- package/src/services/document/blanklines/helpers/tableGuards.ts +21 -0
- package/src/services/document/blanklines/index.ts +67 -0
- package/src/services/document/blanklines/rules/additionRules.ts +337 -0
- package/src/services/document/blanklines/rules/indentationRules.ts +317 -0
- package/src/services/document/blanklines/rules/removalRules.ts +362 -0
- package/src/services/document/blanklines/rules/ruleTypes.ts +92 -0
- package/src/services/document/blanklines/types.ts +29 -0
- package/src/services/document/helpers/ImageBorderCropper.ts +377 -0
- package/src/services/document/helpers/__tests__/whitespace.test.ts +272 -0
- package/src/services/document/helpers/whitespace.ts +117 -0
- package/src/services/document/list/ListNormalizer.ts +947 -0
- package/src/services/document/list/index.ts +45 -0
- package/src/services/document/list/list-detection.ts +275 -0
- package/src/services/document/list/list-types.ts +162 -0
- package/src/services/document/processors/HyperlinkProcessor.ts +370 -0
- package/src/services/document/processors/ListProcessor.ts +257 -0
- package/src/services/document/processors/StructureProcessor.ts +176 -0
- package/src/services/document/processors/StyleProcessor.ts +389 -0
- package/src/services/document/processors/TableProcessor.ts +2238 -0
- package/src/services/document/processors/__tests__/HyperlinkProcessor.test.ts +314 -0
- package/src/services/document/processors/__tests__/ListProcessor.test.ts +291 -0
- package/src/services/document/processors/__tests__/StructureProcessor.test.ts +257 -0
- package/src/services/document/processors/__tests__/TableProcessor.hlp-tips-bullets.test.ts +459 -0
- package/src/services/document/processors/__tests__/TableProcessor.test.ts +1604 -0
- package/src/services/document/processors/index.ts +28 -0
- package/src/services/document/types/docx-processing.ts +310 -0
- package/src/services/editor/EditorActionHandlers.ts +901 -0
- package/src/services/editor/index.ts +13 -0
- package/src/setupTests.ts +47 -0
- package/src/styles/global.css +782 -0
- package/src/types/backup.ts +132 -0
- package/src/types/dictionary.ts +125 -0
- package/src/types/document-processing.ts +331 -0
- package/src/types/docxmlater-augments.d.ts +142 -0
- package/src/types/editor.ts +280 -0
- package/src/types/electron.ts +340 -0
- package/src/types/globalStats.ts +155 -0
- package/src/types/hyperlink.ts +471 -0
- package/src/types/operations.ts +354 -0
- package/src/types/session.ts +427 -0
- package/src/types/settings.ts +112 -0
- package/src/utils/MemoryMonitor.ts +248 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/colorConvert.ts +306 -0
- package/src/utils/diffUtils.ts +347 -0
- package/src/utils/documentUtils.ts +202 -0
- package/src/utils/electronGuard.ts +62 -0
- package/src/utils/indexedDB.ts +915 -0
- package/src/utils/logger.ts +717 -0
- package/src/utils/pathSecurity.ts +232 -0
- package/src/utils/pathValidator.ts +236 -0
- package/src/utils/processingTimeEstimator.ts +153 -0
- package/src/utils/safeJsonParse.ts +62 -0
- package/src/utils/textSanitizer.ts +162 -0
- package/src/utils/urlHelpers.ts +304 -0
- package/src/utils/urlPatterns.ts +198 -0
- package/src/utils/urlSanitizer.ts +152 -0
- package/src/vite-env.d.ts +11 -0
- package/tsconfig.electron.json +19 -0
- package/tsconfig.json +36 -0
- package/tsconfig.node.json +12 -0
- package/typedoc.json +45 -0
- package/vite.config.ts +152 -0
|
@@ -0,0 +1,717 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Professional Logging Utility powered by electron-log
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - File logging with automatic rotation (5MB per file, 5 files max = 25MB total)
|
|
6
|
+
* - Separate logs for main and renderer processes
|
|
7
|
+
* - Environment-aware (debug logs disabled in production)
|
|
8
|
+
* - Colored console output in development
|
|
9
|
+
* - Timestamps and namespaces for better debugging
|
|
10
|
+
* - IPC-safe (renderer logs appear in main console)
|
|
11
|
+
* - Structured logging support
|
|
12
|
+
* - Performance timing utilities
|
|
13
|
+
*
|
|
14
|
+
* Log Locations:
|
|
15
|
+
* - Windows: ~/Documents/Documentation Hub/logs/
|
|
16
|
+
* - macOS: ~/Library/Logs/Documentation Hub/
|
|
17
|
+
* - Linux: ~/.config/Documentation Hub/logs/
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { logger } from '@/utils/logger';
|
|
22
|
+
*
|
|
23
|
+
* const log = logger.namespace('MyModule');
|
|
24
|
+
* log.debug('Detailed info'); // Only in development
|
|
25
|
+
* log.info('Important event'); // Always shows
|
|
26
|
+
* log.warn('Warning message');
|
|
27
|
+
* log.error('Error occurred', error);
|
|
28
|
+
*
|
|
29
|
+
* // Performance timing
|
|
30
|
+
* const timer = logger.startTimer('Operation');
|
|
31
|
+
* // ... do work ...
|
|
32
|
+
* timer.end(); // Logs duration
|
|
33
|
+
*
|
|
34
|
+
* // Structured logging
|
|
35
|
+
* log.info('Document processed', { docId: '123', duration: 1234 });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import electronLog from 'electron-log';
|
|
40
|
+
|
|
41
|
+
// Detect environment
|
|
42
|
+
const isDevelopment = process.env.NODE_ENV !== 'production';
|
|
43
|
+
const isTest = process.env.NODE_ENV === 'test';
|
|
44
|
+
|
|
45
|
+
// Detect if we're in renderer process
|
|
46
|
+
// NOTE: With contextIsolation: true, window.process is not available
|
|
47
|
+
// So we check for window and document (browser-like environment)
|
|
48
|
+
// Main process has 'electron' in process.versions, renderer has window/document
|
|
49
|
+
const isRenderer = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
50
|
+
|
|
51
|
+
// In renderer process, electron-log only has console transport and uses IPC for file logging
|
|
52
|
+
// In main process, it has both file and console transports
|
|
53
|
+
// We should only configure transports in the main process
|
|
54
|
+
const isMainProcess = !isRenderer;
|
|
55
|
+
|
|
56
|
+
// Only configure electron-log if we're in the main process
|
|
57
|
+
if (isMainProcess) {
|
|
58
|
+
// Prevent EPIPE crashes when stdout/stderr pipes are closed (e.g., during shutdown)
|
|
59
|
+
if (process.stdout && typeof process.stdout.on === 'function') {
|
|
60
|
+
process.stdout.on('error', (err: any) => {
|
|
61
|
+
if (err?.code === 'EPIPE') return;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (process.stderr && typeof process.stderr.on === 'function') {
|
|
65
|
+
process.stderr.on('error', (err: any) => {
|
|
66
|
+
if (err?.code === 'EPIPE') return;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (electronLog.transports?.file) {
|
|
71
|
+
electronLog.transports.file.level = 'info';
|
|
72
|
+
electronLog.transports.file.maxSize = 5 * 1024 * 1024; // 5MB per file
|
|
73
|
+
electronLog.transports.file.archiveLogFn = (file: any) => {
|
|
74
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
75
|
+
return file.toString().replace(/\.log$/, `-${timestamp}.log`);
|
|
76
|
+
};
|
|
77
|
+
electronLog.transports.file.format = '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (electronLog.transports?.console) {
|
|
81
|
+
electronLog.transports.console.level = isDevelopment ? 'debug' : 'warn';
|
|
82
|
+
|
|
83
|
+
// Wrap console transport writeFn to suppress EPIPE errors
|
|
84
|
+
const originalWriteFn = electronLog.transports.console.writeFn;
|
|
85
|
+
if (typeof originalWriteFn === 'function') {
|
|
86
|
+
electronLog.transports.console.writeFn = function (...args: any[]) {
|
|
87
|
+
try {
|
|
88
|
+
return originalWriteFn.apply(this, args as [any]);
|
|
89
|
+
} catch (err: any) {
|
|
90
|
+
if (err?.code === 'EPIPE') return;
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Console configuration (development only)
|
|
97
|
+
if (isDevelopment) {
|
|
98
|
+
electronLog.transports.console.format = '[{h}:{i}:{s}.{ms}] [{level}] {text}';
|
|
99
|
+
electronLog.transports.console.useStyles = true;
|
|
100
|
+
} else {
|
|
101
|
+
// Production: minimal console output
|
|
102
|
+
electronLog.transports.console.format = '[{level}] {text}';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Disable logging in tests
|
|
107
|
+
if (isTest && electronLog.transports?.file && electronLog.transports?.console) {
|
|
108
|
+
electronLog.transports.file.level = false;
|
|
109
|
+
electronLog.transports.console.level = false;
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
// Renderer process: Use console transport only, electron-log handles IPC automatically
|
|
113
|
+
// This prevents the "logger isn't initialized in main process" error
|
|
114
|
+
if (electronLog.transports?.console) {
|
|
115
|
+
electronLog.transports.console.level = isDevelopment ? 'debug' : 'warn';
|
|
116
|
+
electronLog.transports.console.format = '[{h}:{i}:{s}.{ms}] [{level}] {text}';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Disable file transport attempts in renderer (it uses IPC automatically when available)
|
|
120
|
+
if (electronLog.transports?.file) {
|
|
121
|
+
electronLog.transports.file.level = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* SECURITY: Sanitize log data to prevent sensitive information exposure
|
|
127
|
+
*
|
|
128
|
+
* Redacts:
|
|
129
|
+
* - File paths (Windows: C:\..., Unix: /home/...)
|
|
130
|
+
* - API endpoints and URLs
|
|
131
|
+
* - Document content (truncates long strings)
|
|
132
|
+
* - Sensitive field names (apiEndpoint, filePath, documentPath, token, password, etc.)
|
|
133
|
+
*
|
|
134
|
+
* @param data - Any data to be logged
|
|
135
|
+
* @returns Sanitized version safe for logging
|
|
136
|
+
*/
|
|
137
|
+
function sanitizeLogData(data: any): any {
|
|
138
|
+
// Handle null/undefined
|
|
139
|
+
if (data == null) {
|
|
140
|
+
return data;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Handle primitive types
|
|
144
|
+
if (typeof data === 'string') {
|
|
145
|
+
let sanitized = data;
|
|
146
|
+
|
|
147
|
+
// Redact Windows file paths (C:\Users\..., D:\Documents\..., etc.)
|
|
148
|
+
sanitized = sanitized.replace(/[A-Z]:\\[^\s"'<>|*?]+/gi, '[REDACTED_PATH]');
|
|
149
|
+
|
|
150
|
+
// Redact UNC paths (\\server\share\...)
|
|
151
|
+
sanitized = sanitized.replace(/\\\\[^\s"'<>|*?]+/g, '[REDACTED_PATH]');
|
|
152
|
+
|
|
153
|
+
// Redact Unix file paths (/home/..., /Users/..., /var/..., etc.)
|
|
154
|
+
sanitized = sanitized.replace(/\/(home|Users|var|tmp|opt)\/[\w\s\-./]+/gi, '[REDACTED_PATH]');
|
|
155
|
+
|
|
156
|
+
// Redact full URLs (but keep domain for debugging)
|
|
157
|
+
sanitized = sanitized.replace(/(https?:\/\/[^/\s]+)(\/[^\s]*)/gi, '$1/[REDACTED_URL]');
|
|
158
|
+
|
|
159
|
+
// Truncate very long strings (likely document content)
|
|
160
|
+
if (sanitized.length > 500) {
|
|
161
|
+
sanitized = sanitized.substring(0, 500) + '... [TRUNCATED]';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return sanitized;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Handle arrays
|
|
168
|
+
if (Array.isArray(data)) {
|
|
169
|
+
return data.map((item) => sanitizeLogData(item));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Handle objects
|
|
173
|
+
if (typeof data === 'object') {
|
|
174
|
+
const sanitized: any = {};
|
|
175
|
+
const sensitiveKeys = [
|
|
176
|
+
'apiEndpoint',
|
|
177
|
+
'apiUrl',
|
|
178
|
+
'filePath',
|
|
179
|
+
'documentPath',
|
|
180
|
+
'path',
|
|
181
|
+
'fullPath',
|
|
182
|
+
'token',
|
|
183
|
+
'accessToken',
|
|
184
|
+
'refreshToken',
|
|
185
|
+
'apiKey',
|
|
186
|
+
'password',
|
|
187
|
+
'secret',
|
|
188
|
+
'clientSecret',
|
|
189
|
+
'authorization',
|
|
190
|
+
'bearer',
|
|
191
|
+
'cookie',
|
|
192
|
+
'sessionId',
|
|
193
|
+
'userId',
|
|
194
|
+
'email',
|
|
195
|
+
'username',
|
|
196
|
+
'connectionString',
|
|
197
|
+
'privateKey',
|
|
198
|
+
'credential',
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
for (const [key, value] of Object.entries(data)) {
|
|
202
|
+
// Redact sensitive fields entirely
|
|
203
|
+
if (sensitiveKeys.some((sk) => key.toLowerCase().includes(sk.toLowerCase()))) {
|
|
204
|
+
sanitized[key] = '[REDACTED]';
|
|
205
|
+
} else {
|
|
206
|
+
// Recursively sanitize nested objects
|
|
207
|
+
sanitized[key] = sanitizeLogData(value);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return sanitized;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Return other types (numbers, booleans) as-is
|
|
215
|
+
return data;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get formatted timestamp for manual logging
|
|
220
|
+
*/
|
|
221
|
+
function getTimestamp(): string {
|
|
222
|
+
const now = new Date();
|
|
223
|
+
const hours = String(now.getHours()).padStart(2, '0');
|
|
224
|
+
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
225
|
+
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
226
|
+
const ms = String(now.getMilliseconds()).padStart(3, '0');
|
|
227
|
+
return `${hours}:${minutes}:${seconds}.${ms}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Create a scoped logger for a specific module
|
|
232
|
+
*/
|
|
233
|
+
function createScopedLogger(scope: string) {
|
|
234
|
+
// In renderer, only use console logging to avoid "not initialized" errors
|
|
235
|
+
// electron-log will automatically send logs to main process via IPC when properly set up
|
|
236
|
+
const useElectronLog = isMainProcess;
|
|
237
|
+
const scopedLog = useElectronLog ? electronLog.scope(scope) : null;
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
/**
|
|
241
|
+
* Debug level - only enabled in development
|
|
242
|
+
* Use for detailed diagnostic information
|
|
243
|
+
*/
|
|
244
|
+
debug(message: string, ...args: any[]): void {
|
|
245
|
+
if (isDevelopment && !isTest) {
|
|
246
|
+
// SECURITY: Sanitize all arguments before logging
|
|
247
|
+
const sanitizedArgs = args.map(sanitizeLogData);
|
|
248
|
+
const sanitizedMessage = sanitizeLogData(message);
|
|
249
|
+
|
|
250
|
+
if (scopedLog) {
|
|
251
|
+
scopedLog.debug(sanitizedMessage, ...sanitizedArgs);
|
|
252
|
+
} else {
|
|
253
|
+
// Renderer fallback: use console directly
|
|
254
|
+
console.debug(`[${scope}] [DEBUG] ${sanitizedMessage}`, ...sanitizedArgs);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Info level - general informational messages
|
|
261
|
+
* Enabled in all environments
|
|
262
|
+
*/
|
|
263
|
+
info(message: string, ...args: any[]): void {
|
|
264
|
+
if (!isTest) {
|
|
265
|
+
// SECURITY: Sanitize all arguments before logging
|
|
266
|
+
const sanitizedArgs = args.map(sanitizeLogData);
|
|
267
|
+
const sanitizedMessage = sanitizeLogData(message);
|
|
268
|
+
|
|
269
|
+
if (scopedLog) {
|
|
270
|
+
scopedLog.info(sanitizedMessage, ...sanitizedArgs);
|
|
271
|
+
} else {
|
|
272
|
+
console.info(`[${scope}] [INFO] ${sanitizedMessage}`, ...sanitizedArgs);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Warning level - potentially harmful situations
|
|
279
|
+
* Enabled in all environments
|
|
280
|
+
*/
|
|
281
|
+
warn(message: string, ...args: any[]): void {
|
|
282
|
+
if (!isTest) {
|
|
283
|
+
// SECURITY: Sanitize all arguments before logging
|
|
284
|
+
const sanitizedArgs = args.map(sanitizeLogData);
|
|
285
|
+
const sanitizedMessage = sanitizeLogData(message);
|
|
286
|
+
|
|
287
|
+
if (scopedLog) {
|
|
288
|
+
scopedLog.warn(sanitizedMessage, ...sanitizedArgs);
|
|
289
|
+
} else {
|
|
290
|
+
console.warn(`[${scope}] [WARN] ${sanitizedMessage}`, ...sanitizedArgs);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Error level - error events
|
|
297
|
+
* Always enabled
|
|
298
|
+
*/
|
|
299
|
+
error(message: string, ...args: any[]): void {
|
|
300
|
+
// SECURITY: Sanitize all arguments before logging
|
|
301
|
+
const sanitizedArgs = args.map(sanitizeLogData);
|
|
302
|
+
const sanitizedMessage = sanitizeLogData(message);
|
|
303
|
+
|
|
304
|
+
if (scopedLog) {
|
|
305
|
+
scopedLog.error(sanitizedMessage, ...sanitizedArgs);
|
|
306
|
+
} else {
|
|
307
|
+
console.error(`[${scope}] [ERROR] ${sanitizedMessage}`, ...sanitizedArgs);
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Verbose level - very detailed logs
|
|
313
|
+
* Only in development with explicit enable
|
|
314
|
+
*/
|
|
315
|
+
verbose(message: string, ...args: any[]): void {
|
|
316
|
+
if (isDevelopment && !isTest) {
|
|
317
|
+
const sanitizedArgs = args.map(sanitizeLogData);
|
|
318
|
+
const sanitizedMessage = sanitizeLogData(message);
|
|
319
|
+
if (scopedLog) {
|
|
320
|
+
scopedLog.verbose(sanitizedMessage, ...sanitizedArgs);
|
|
321
|
+
} else {
|
|
322
|
+
console.log(`[${scope}] [VERBOSE] ${sanitizedMessage}`, ...sanitizedArgs);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Silly level - extremely detailed logs
|
|
329
|
+
* Only in development with explicit enable
|
|
330
|
+
*/
|
|
331
|
+
silly(message: string, ...args: any[]): void {
|
|
332
|
+
if (isDevelopment && !isTest) {
|
|
333
|
+
const sanitizedArgs = args.map(sanitizeLogData);
|
|
334
|
+
const sanitizedMessage = sanitizeLogData(message);
|
|
335
|
+
if (scopedLog) {
|
|
336
|
+
scopedLog.silly(sanitizedMessage, ...sanitizedArgs);
|
|
337
|
+
} else {
|
|
338
|
+
console.log(`[${scope}] [SILLY] ${sanitizedMessage}`, ...sanitizedArgs);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Main logger export with utility methods
|
|
347
|
+
*/
|
|
348
|
+
export const logger = {
|
|
349
|
+
/**
|
|
350
|
+
* Debug level logging - only enabled in development
|
|
351
|
+
*/
|
|
352
|
+
debug(message: string, ...args: any[]): void {
|
|
353
|
+
if (isDevelopment && !isTest) {
|
|
354
|
+
if (isMainProcess) {
|
|
355
|
+
electronLog.debug(message, ...args);
|
|
356
|
+
} else {
|
|
357
|
+
console.debug(`[DEBUG] ${message}`, ...args);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Info level logging - enabled in all environments
|
|
364
|
+
*/
|
|
365
|
+
info(message: string, ...args: any[]): void {
|
|
366
|
+
if (!isTest) {
|
|
367
|
+
if (isMainProcess) {
|
|
368
|
+
electronLog.info(message, ...args);
|
|
369
|
+
} else {
|
|
370
|
+
console.info(`[INFO] ${message}`, ...args);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Warning level logging - enabled in all environments
|
|
377
|
+
*/
|
|
378
|
+
warn(message: string, ...args: any[]): void {
|
|
379
|
+
if (!isTest) {
|
|
380
|
+
if (isMainProcess) {
|
|
381
|
+
electronLog.warn(message, ...args);
|
|
382
|
+
} else {
|
|
383
|
+
console.warn(`[WARN] ${message}`, ...args);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Error level logging - always enabled
|
|
390
|
+
*/
|
|
391
|
+
error(message: string, ...args: any[]): void {
|
|
392
|
+
if (isMainProcess) {
|
|
393
|
+
electronLog.error(message, ...args);
|
|
394
|
+
} else {
|
|
395
|
+
console.error(`[ERROR] ${message}`, ...args);
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Verbose level logging
|
|
401
|
+
*/
|
|
402
|
+
verbose(message: string, ...args: any[]): void {
|
|
403
|
+
if (isDevelopment && !isTest) {
|
|
404
|
+
if (isMainProcess) {
|
|
405
|
+
electronLog.verbose(message, ...args);
|
|
406
|
+
} else {
|
|
407
|
+
console.log(`[VERBOSE] ${message}`, ...args);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Create a namespaced logger for specific modules
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* const log = logger.namespace('DocumentProcessor');
|
|
417
|
+
* log.info('Processing started');
|
|
418
|
+
*/
|
|
419
|
+
namespace(name: string) {
|
|
420
|
+
return createScopedLogger(name);
|
|
421
|
+
},
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Create a scoped logger (alias for namespace)
|
|
425
|
+
*/
|
|
426
|
+
scope(name: string) {
|
|
427
|
+
return createScopedLogger(name);
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Get the path to the log file
|
|
432
|
+
*/
|
|
433
|
+
getLogPath(): string {
|
|
434
|
+
if (electronLog.transports?.file) {
|
|
435
|
+
return electronLog.transports.file.getFile().path;
|
|
436
|
+
}
|
|
437
|
+
return 'Logs not available in renderer';
|
|
438
|
+
},
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Set log level dynamically at runtime
|
|
442
|
+
*
|
|
443
|
+
* @param level - Log level (error, warn, info, debug, verbose, silly, false)
|
|
444
|
+
*/
|
|
445
|
+
setLevel(level: 'error' | 'warn' | 'info' | 'debug' | 'verbose' | 'silly' | false): void {
|
|
446
|
+
if (electronLog.transports?.file) {
|
|
447
|
+
electronLog.transports.file.level = level;
|
|
448
|
+
}
|
|
449
|
+
if (electronLog.transports?.console) {
|
|
450
|
+
electronLog.transports.console.level = level;
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Enable or disable file logging
|
|
456
|
+
*/
|
|
457
|
+
setFileLogging(enabled: boolean): void {
|
|
458
|
+
if (electronLog.transports?.file) {
|
|
459
|
+
electronLog.transports.file.level = enabled ? 'info' : false;
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Clear all log files
|
|
465
|
+
* Note: This function uses dynamic imports to avoid bundling Node.js modules in renderer
|
|
466
|
+
*/
|
|
467
|
+
async clearLogs(): Promise<void> {
|
|
468
|
+
try {
|
|
469
|
+
if (!electronLog.transports?.file?.getFile) {
|
|
470
|
+
throw new Error('File logging not available');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Dynamic imports to avoid Vite bundling Node.js built-ins
|
|
474
|
+
const fs = await import('fs/promises');
|
|
475
|
+
const path = await import('path');
|
|
476
|
+
|
|
477
|
+
const logPath = electronLog.transports.file.getFile().path;
|
|
478
|
+
const logDir = path.dirname(logPath);
|
|
479
|
+
|
|
480
|
+
const files = await fs.readdir(logDir);
|
|
481
|
+
for (const file of files) {
|
|
482
|
+
if (file.endsWith('.log')) {
|
|
483
|
+
await fs.unlink(path.join(logDir, file));
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
electronLog.info('Log files cleared');
|
|
488
|
+
} catch (error) {
|
|
489
|
+
electronLog.error('Failed to clear logs:', error);
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Performance measurement utility
|
|
496
|
+
* Use to measure execution time of operations
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* const timer = startTimer('Document Processing');
|
|
500
|
+
* await processDocument();
|
|
501
|
+
* timer.end(); // Logs: "[DocumentProcessing] took 1234ms"
|
|
502
|
+
*/
|
|
503
|
+
export function startTimer(operationName: string) {
|
|
504
|
+
const start = performance.now();
|
|
505
|
+
const log = logger.namespace('Timer');
|
|
506
|
+
|
|
507
|
+
return {
|
|
508
|
+
/**
|
|
509
|
+
* End the timer and log the duration
|
|
510
|
+
*/
|
|
511
|
+
end(): number {
|
|
512
|
+
const duration = Math.round(performance.now() - start);
|
|
513
|
+
log.debug(`${operationName} took ${duration}ms`);
|
|
514
|
+
return duration;
|
|
515
|
+
},
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Get current elapsed time without logging
|
|
519
|
+
*/
|
|
520
|
+
elapsed(): number {
|
|
521
|
+
return Math.round(performance.now() - start);
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Direct access to electron-log for advanced usage
|
|
528
|
+
* Only use if you need features not exposed by the wrapper
|
|
529
|
+
*/
|
|
530
|
+
export const electronLogger = electronLog;
|
|
531
|
+
|
|
532
|
+
// Export for backward compatibility
|
|
533
|
+
export default logger;
|
|
534
|
+
|
|
535
|
+
// ============================================================================
|
|
536
|
+
// DEBUG MODE UTILITIES
|
|
537
|
+
// Toggleable verbose logging for specific subsystems
|
|
538
|
+
// ============================================================================
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Debug mode flags for enabling verbose logging in specific areas.
|
|
542
|
+
* These can be toggled at runtime via localStorage for troubleshooting.
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
* ```typescript
|
|
546
|
+
* import { debugModes, setDebugMode, isDebugEnabled } from '@/utils/logger';
|
|
547
|
+
*
|
|
548
|
+
* // Enable document processing debug logs
|
|
549
|
+
* setDebugMode(debugModes.DOCUMENT_PROCESSING, true);
|
|
550
|
+
*
|
|
551
|
+
* // Check if debug is enabled before verbose logging
|
|
552
|
+
* if (isDebugEnabled(debugModes.SESSION_STATE)) {
|
|
553
|
+
* log.debug('Detailed session state:', state);
|
|
554
|
+
* }
|
|
555
|
+
* ```
|
|
556
|
+
*/
|
|
557
|
+
export const debugModes = {
|
|
558
|
+
/** Verbose logging for document processing operations */
|
|
559
|
+
DOCUMENT_PROCESSING: 'debug:documentProcessing',
|
|
560
|
+
/** Verbose logging for session state transitions */
|
|
561
|
+
SESSION_STATE: 'debug:sessionState',
|
|
562
|
+
/** Verbose logging for IPC calls between main/renderer */
|
|
563
|
+
IPC_CALLS: 'debug:ipcCalls',
|
|
564
|
+
/** Verbose logging for IndexedDB operations */
|
|
565
|
+
DATABASE: 'debug:database',
|
|
566
|
+
/** Verbose logging for hyperlink operations */
|
|
567
|
+
HYPERLINKS: 'debug:hyperlinks',
|
|
568
|
+
/** Verbose logging for backup operations */
|
|
569
|
+
BACKUPS: 'debug:backups',
|
|
570
|
+
/** Verbose logging for list/bullet processing operations */
|
|
571
|
+
LIST_PROCESSING: 'debug:listProcessing',
|
|
572
|
+
} as const;
|
|
573
|
+
|
|
574
|
+
export type DebugMode = (typeof debugModes)[keyof typeof debugModes];
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Check if a specific debug mode is enabled.
|
|
578
|
+
*
|
|
579
|
+
* @param mode - The debug mode to check (use debugModes constants)
|
|
580
|
+
* @returns true if the debug mode is enabled
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```typescript
|
|
584
|
+
* if (isDebugEnabled(debugModes.DOCUMENT_PROCESSING)) {
|
|
585
|
+
* log.debug('Processing details:', { step: 1, data: processingData });
|
|
586
|
+
* }
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
export function isDebugEnabled(mode: DebugMode): boolean {
|
|
590
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
return localStorage.getItem(mode) === 'true';
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Enable or disable a specific debug mode.
|
|
598
|
+
*
|
|
599
|
+
* @param mode - The debug mode to set (use debugModes constants)
|
|
600
|
+
* @param enabled - Whether to enable (true) or disable (false) the mode
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* // Enable debug mode for troubleshooting
|
|
605
|
+
* setDebugMode(debugModes.SESSION_STATE, true);
|
|
606
|
+
*
|
|
607
|
+
* // Disable when done
|
|
608
|
+
* setDebugMode(debugModes.SESSION_STATE, false);
|
|
609
|
+
* ```
|
|
610
|
+
*/
|
|
611
|
+
export function setDebugMode(mode: DebugMode, enabled: boolean): void {
|
|
612
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
if (enabled) {
|
|
616
|
+
localStorage.setItem(mode, 'true');
|
|
617
|
+
} else {
|
|
618
|
+
localStorage.removeItem(mode);
|
|
619
|
+
}
|
|
620
|
+
const log = logger.namespace('Debug');
|
|
621
|
+
log.info(`Debug mode ${mode} ${enabled ? 'enabled' : 'disabled'}`);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Get all currently enabled debug modes.
|
|
626
|
+
*
|
|
627
|
+
* @returns Array of enabled debug mode keys
|
|
628
|
+
*
|
|
629
|
+
* @example
|
|
630
|
+
* ```typescript
|
|
631
|
+
* const enabled = getEnabledDebugModes();
|
|
632
|
+
* console.log('Active debug modes:', enabled);
|
|
633
|
+
* // Output: ['debug:documentProcessing', 'debug:hyperlinks']
|
|
634
|
+
* ```
|
|
635
|
+
*/
|
|
636
|
+
export function getEnabledDebugModes(): DebugMode[] {
|
|
637
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
638
|
+
return [];
|
|
639
|
+
}
|
|
640
|
+
return Object.values(debugModes).filter(
|
|
641
|
+
(mode) => localStorage.getItem(mode) === 'true'
|
|
642
|
+
) as DebugMode[];
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Disable all debug modes.
|
|
647
|
+
* Useful for resetting debug state after troubleshooting.
|
|
648
|
+
*/
|
|
649
|
+
export function disableAllDebugModes(): void {
|
|
650
|
+
const log = logger.namespace('Debug');
|
|
651
|
+
Object.values(debugModes).forEach((mode) => {
|
|
652
|
+
if (typeof localStorage !== 'undefined') {
|
|
653
|
+
localStorage.removeItem(mode);
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
log.info('All debug modes disabled');
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Create a conditional logger that only logs when a debug mode is enabled.
|
|
661
|
+
* Useful for adding verbose debug logging without impacting performance.
|
|
662
|
+
*
|
|
663
|
+
* @param mode - The debug mode that controls this logger
|
|
664
|
+
* @param namespace - The namespace for log messages
|
|
665
|
+
* @returns A logger that only logs when the mode is enabled
|
|
666
|
+
*
|
|
667
|
+
* @example
|
|
668
|
+
* ```typescript
|
|
669
|
+
* const debugLog = createDebugLogger(debugModes.DOCUMENT_PROCESSING, 'DocProcessor');
|
|
670
|
+
*
|
|
671
|
+
* // These only log when debug:documentProcessing is enabled
|
|
672
|
+
* debugLog.debug('Step 1: Loading document');
|
|
673
|
+
* debugLog.info('Processing complete', { stats });
|
|
674
|
+
* ```
|
|
675
|
+
*/
|
|
676
|
+
export function createDebugLogger(mode: DebugMode, namespace: string) {
|
|
677
|
+
const log = logger.namespace(namespace);
|
|
678
|
+
|
|
679
|
+
return {
|
|
680
|
+
debug: (...args: unknown[]) => {
|
|
681
|
+
if (isDebugEnabled(mode)) (log.debug as (...args: unknown[]) => void)(...args);
|
|
682
|
+
},
|
|
683
|
+
info: (...args: unknown[]) => {
|
|
684
|
+
if (isDebugEnabled(mode)) (log.info as (...args: unknown[]) => void)(...args);
|
|
685
|
+
},
|
|
686
|
+
warn: (...args: unknown[]) => {
|
|
687
|
+
// Warnings always log
|
|
688
|
+
(log.warn as (...args: unknown[]) => void)(...args);
|
|
689
|
+
},
|
|
690
|
+
error: (...args: unknown[]) => {
|
|
691
|
+
// Errors always log
|
|
692
|
+
(log.error as (...args: unknown[]) => void)(...args);
|
|
693
|
+
},
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Initialize logging on startup (call from main process)
|
|
699
|
+
*/
|
|
700
|
+
export function initializeLogging(): void {
|
|
701
|
+
const log = logger.namespace('Logger');
|
|
702
|
+
|
|
703
|
+
log.info('═══════════════════════════════════════════════════════════');
|
|
704
|
+
log.info(' Documentation Hub - Logging Initialized');
|
|
705
|
+
log.info('═══════════════════════════════════════════════════════════');
|
|
706
|
+
log.info(`Environment: ${process.env.NODE_ENV || 'development'}`);
|
|
707
|
+
log.info(`Process: ${isRenderer ? 'Renderer' : 'Main'}`);
|
|
708
|
+
|
|
709
|
+
if (electronLog.transports?.file) {
|
|
710
|
+
log.info(`Log file: ${electronLog.transports.file.getFile().path}`);
|
|
711
|
+
log.info(
|
|
712
|
+
`Log level: File=${electronLog.transports.file.level}, Console=${electronLog.transports.console?.level || 'N/A'}`
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
log.info('═══════════════════════════════════════════════════════════');
|
|
717
|
+
}
|