diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..2a1615b --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,14 @@ +root: true +parser: '@typescript-eslint/parser' +parserOptions: + project: './tsconfig.json' +plugins: + - '@typescript-eslint' +extends: + - eslint:recommended + - plugin:@typescript-eslint/recommended +env: + node: true + es2022: true +rules: + '@typescript-eslint/no-unsafe-member-access': 'off' diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f6c47..4e61f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,37 +6,62 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## [Unreleased] +## [1.2.1] - 2024-11-19 + +### Added + +- Added Codacy Code Quality Badge to `README.md` + +### Fixed + +- Fixed TypeScript ES2022 issues + ## [1.2.0] - 2024-11-17 + ### Added + - Comprehensive bug report template - Detailed feature request template + ### Changed + - Settings are now saved in the workspace instead of globally in the USER. ## [1.1.0] - 2024-11-16 + ### Added + - Improved the user interface of the webview panel. - Added line number formatting with leading zeros. - Removed timestamp and dot from log entries in the summary. + ### Changed + - Log levels are now displayed in uppercase format (e.g. ERROR, WARN, DEBUG, INFO, ...) ### Fixed + - Fixed potential security issue with non-literal argument in `fs.existsSync`. - Fixed potential object injection issue in `groupLogEntries` method. ## [1.0.2] - 2024-10-10 + ### Changed + - Repository URL to `https://github.com/OpenForgeProject/vscode-ext-magento-log-viewer` ## v1.0.1 + ### Added + - Extension Logo - Screenshot in the README file. - Added a "Getting Started" section to the README. ## v1.0.0 + ### Added + - View log files in the `var/log` directory of your Magento project. - Open log files directly in the editor by clicking on them in the tree view. - Expand log files to view individual lines. @@ -46,5 +71,6 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how - Repository field in `package.json`. ### Changed + - Status bar item now shows the total number of log entries instead of the number of log files. - Updated README to reflect the change in the status bar item text. diff --git a/README.md b/README.md index bd8314d..f68e1fd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Magento Log Viewer +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/04d20d74a4bb4f7fb144d320f7008edb)](https://app.codacy.com/gh/OpenForgeProject/vscode-ext-magento-log-viewer/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) + The Magento Log Viewer extension for Visual Studio Code provides a convenient way to view and manage Magento log files directly in your workspace. ## Features diff --git a/package-lock.json b/package-lock.json index e9c55fa..637c16d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magento-log-viewer", - "version": "0.0.1", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magento-log-viewer", - "version": "0.0.1", + "version": "1.2.0", "devDependencies": { "@types/mocha": "^10.0.9", "@types/node": "20.x", diff --git a/package.json b/package.json index a29c8b2..5589c50 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "magento-log-viewer", "displayName": "Magento Log Viewer", "description": "A Visual Studio Code extension to view and manage Magento log files.", - "version": "1.2.0", + "version": "1.2.1", "publisher": "MathiasElle", "icon": "resources/logo.png", "repository": { @@ -118,6 +118,7 @@ "webpack": "^5.95.0", "webpack-cli": "^5.1.4", "@vscode/test-cli": "^0.0.10", - "@vscode/test-electron": "^2.4.1" + "@vscode/test-electron": "^2.4.1", + "vscode": "^1.78.0" } } diff --git a/src/extension.ts b/src/extension.ts index a9bf5a0..a10b2a1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -15,9 +15,13 @@ export function activate(context: vscode.ExtensionContext) { const workspaceFolders = vscode.workspace.workspaceFolders; const defaultUri = workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0].uri : undefined; vscode.window.showOpenDialog({ defaultUri, canSelectFolders: true, canSelectMany: false, openLabel: 'Select Magento Root Folder' }).then(folderUri => { - if (folderUri && folderUri[0]) { + if (folderUri?.[0]) { config.update('magentoLogViewer.magentoRoot', folderUri[0].fsPath, vscode.ConfigurationTarget.Workspace).then(() => { - vscode.window.showInformationMessage('Magento root folder successfully saved!'); + try { + vscode.window.showInformationMessage('Magento root folder successfully saved!'); + } catch (error) { + console.error('Failed to show information message:', error instanceof Error ? error.message : String(error)); + } config.update('magentoLogViewer.isMagentoProject', 'Yes', vscode.ConfigurationTarget.Workspace); activateExtension(context, folderUri[0].fsPath); }); @@ -32,7 +36,11 @@ export function activate(context: vscode.ExtensionContext) { } else if (isMagentoProject === 'Yes') { const magentoRoot = config.get('magentoLogViewer.magentoRoot', ''); if (!magentoRoot || !isValidPath(magentoRoot)) { - vscode.window.showErrorMessage('Magento root path is not set or is not a directory.'); + try { + vscode.window.showErrorMessage('Magento root path is not set or is not a directory.'); + } catch (error) { + console.error('Failed to show error message:', error instanceof Error ? error.message : String(error)); + } return; } activateExtension(context, magentoRoot); @@ -44,17 +52,20 @@ function activateExtension(context: vscode.ExtensionContext, magentoRoot: string const treeView = vscode.window.createTreeView('logFiles', { treeDataProvider: logViewerProvider }); vscode.commands.registerCommand('magento-log-viewer.refreshLogFiles', () => logViewerProvider.refresh()); - vscode.commands.registerCommand('magento-log-viewer.openFile', (filePath, lineNumber) => { - if (lineNumber !== undefined) { - const options: vscode.TextDocumentShowOptions = { - selection: new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, 0)) - }; - vscode.window.showTextDocument(vscode.Uri.file(filePath), options); - } else { - vscode.window.showTextDocument(vscode.Uri.file(filePath)); + vscode.commands.registerCommand('magento-log-viewer.openFile', (filePath: string, lineNumber?: number) => { + + if (typeof filePath === 'string') { + if (lineNumber !== undefined && typeof lineNumber === 'number' && typeof vscode !== 'undefined' && typeof vscode.window !== 'undefined') { + const options: vscode.TextDocumentShowOptions = { + selection: new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, 0)) + }; + vscode.window.showTextDocument(vscode.Uri.file(filePath), options); + } else { + vscode.window.showTextDocument(vscode.Uri.file(filePath)); + } } }); - vscode.commands.registerCommand('magento-log-viewer.openFileAtLine', (filePath, lineNumber) => { + vscode.commands.registerCommand('magento-log-viewer.openFileAtLine', (filePath: string, lineNumber: number) => { const options: vscode.TextDocumentShowOptions = { selection: new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, 0)) }; @@ -67,9 +78,17 @@ function activateExtension(context: vscode.ExtensionContext, magentoRoot: string const files = fs.readdirSync(logPath); files.forEach(file => fs.unlinkSync(path.join(logPath, file))); logViewerProvider.refresh(); - vscode.window.showInformationMessage('All log files have been cleared.'); + try { + vscode.window.showInformationMessage('All log files have been cleared.'); + } catch (error) { + console.error('Failed to show information message:', error instanceof Error ? error.message : String(error)); + } } else { - vscode.window.showInformationMessage('No log files found to clear.'); + try { + vscode.window.showInformationMessage('No log files found to clear.'); + } catch (error) { + console.error('Failed to show information message:', error instanceof Error ? error.message : String(error)); + } } }); diff --git a/src/logViewer.ts b/src/logViewer.ts index 0ddd6b6..e1c9f74 100644 --- a/src/logViewer.ts +++ b/src/logViewer.ts @@ -45,12 +45,28 @@ export class LogViewerProvider implements vscode.TreeDataProvider, vsco } } + private isValidLogDirectory(dir: string): boolean { + const normalizedDir = path.normalize(dir); + const normalizedLogPath = path.normalize(path.join(this.workspaceRoot, 'var', 'log')); + return normalizedDir === normalizedLogPath; + } + public getLogFiles(dir: string): LogFile[] { + if (!this.isValidLogDirectory(dir)) { + console.error('Invalid log directory path'); + return []; + } + if (this.pathExists(dir)) { const files = fs.readdirSync(dir); this.updateBadge(); return files.map(file => { + // Validate file path is within log directory const filePath = path.join(dir, file); + if (!filePath.startsWith(dir)) { + console.error('Invalid file path detected'); + return null; + } const lineCount = this.getLineCount(filePath); const logFile = new LogFile(`${file} (${lineCount})`, vscode.TreeItemCollapsibleState.Collapsed, { command: 'magento-log-viewer.openFile', @@ -60,7 +76,7 @@ export class LogViewerProvider implements vscode.TreeDataProvider, vsco logFile.iconPath = new vscode.ThemeIcon('file'); logFile.children = this.getLogFileLines(filePath); return logFile; - }); + }).filter(Boolean) as LogFile[]; } else { this.updateBadge(); return []; diff --git a/tsconfig.json b/tsconfig.json index 8a79f20..cb35375 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ ], "sourceMap": true, "rootDir": "src", - "strict": true /* enable all strict type-checking options */ + "strict": true, /* enable all strict type-checking options */ /* Additional Checks */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */