sca-tool
Version:
Universal static code analysis tool for calculating API operation costs across multiple frameworks (NestJS, Express, Fastify)
331 lines • 11.7 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.EditorDetector = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
/**
* Editor detection utility for SCA-Tool
*/
class EditorDetector {
static EDITOR_COMMANDS = {
'code': {
command: 'code',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'Visual Studio Code'
},
'code-insiders': {
command: 'code-insiders',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'Visual Studio Code Insiders'
},
'cursor': {
command: 'cursor',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'Cursor'
},
'webstorm': {
command: 'webstorm',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'WebStorm'
},
'idea': {
command: 'idea',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'IntelliJ IDEA'
},
'subl': {
command: 'subl',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'Sublime Text'
},
'atom': {
command: 'atom',
args: [],
supportsLineNumbers: true,
lineNumberFormat: ':line',
name: 'Atom'
},
'vim': {
command: 'vim',
args: [],
supportsLineNumbers: true,
lineNumberFormat: '+line',
name: 'Vim'
},
'nvim': {
command: 'nvim',
args: [],
supportsLineNumbers: true,
lineNumberFormat: '+line',
name: 'Neovim'
},
'emacs': {
command: 'emacs',
args: [],
supportsLineNumbers: true,
lineNumberFormat: '+line',
name: 'Emacs'
}
};
/**
* Detect the available code editor
*/
static detectEditor() {
const detectedEditor = this.findAvailableEditor();
const defaultEditor = detectedEditor || 'code'; // Default to VS Code
return {
defaultEditor,
detectedEditor,
openInEditor: false,
editorCommands: this.EDITOR_COMMANDS,
integration: {
generateVSCodeTasks: detectedEditor === 'code' || detectedEditor === 'code-insiders',
generateEditorConfig: true
}
};
}
/**
* Find the first available editor from the list
*/
static findAvailableEditor() {
// Check environment variables first
const envEditor = process.env.EDITOR || process.env.VISUAL;
if (envEditor) {
const editorName = path.basename(envEditor);
if (this.EDITOR_COMMANDS[editorName]) {
return editorName;
}
}
// Check for VS Code first (most common for TypeScript development)
const priorityOrder = ['code', 'code-insiders', 'cursor', 'webstorm', 'idea', 'subl', 'atom', 'vim', 'nvim', 'emacs'];
for (const editor of priorityOrder) {
if (this.isCommandAvailable(editor)) {
return editor;
}
}
// Check for platform-specific installations
if (process.platform === 'win32') {
return this.detectWindowsEditor();
}
else if (process.platform === 'darwin') {
return this.detectMacEditor();
}
else {
return this.detectLinuxEditor();
}
return undefined;
}
/**
* Check if a command is available in PATH
*/
static isCommandAvailable(command) {
try {
const { execSync } = require('child_process');
const checkCommand = process.platform === 'win32' ? `where ${command}` : `which ${command}`;
execSync(checkCommand, { stdio: 'ignore' });
return true;
}
catch {
return false;
}
}
/**
* Detect editor on Windows
*/
static detectWindowsEditor() {
const commonPaths = [
'C:\\Users\\%USERNAME%\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe',
'C:\\Program Files\\Microsoft VS Code\\Code.exe',
'C:\\Program Files (x86)\\Microsoft VS Code\\Code.exe',
'C:\\Users\\%USERNAME%\\AppData\\Local\\Programs\\cursor\\Cursor.exe'
];
for (const editorPath of commonPaths) {
const expandedPath = editorPath.replace('%USERNAME%', os.userInfo().username);
if (fs.existsSync(expandedPath)) {
if (expandedPath.includes('cursor'))
return 'cursor';
if (expandedPath.includes('Code'))
return 'code';
}
}
return undefined;
}
/**
* Detect editor on macOS
*/
static detectMacEditor() {
const commonPaths = [
'/Applications/Visual Studio Code.app',
'/Applications/Visual Studio Code - Insiders.app',
'/Applications/Cursor.app',
'/Applications/WebStorm.app',
'/Applications/IntelliJ IDEA.app',
'/Applications/Sublime Text.app'
];
for (const editorPath of commonPaths) {
if (fs.existsSync(editorPath)) {
if (editorPath.includes('Cursor'))
return 'cursor';
if (editorPath.includes('Visual Studio Code - Insiders'))
return 'code-insiders';
if (editorPath.includes('Visual Studio Code'))
return 'code';
if (editorPath.includes('WebStorm'))
return 'webstorm';
if (editorPath.includes('IntelliJ'))
return 'idea';
if (editorPath.includes('Sublime'))
return 'subl';
}
}
return undefined;
}
/**
* Detect editor on Linux
*/
static detectLinuxEditor() {
// Linux usually relies on PATH, so this is mostly for completeness
const commonCommands = ['code', 'code-insiders', 'cursor', 'webstorm', 'idea', 'subl'];
for (const command of commonCommands) {
if (this.isCommandAvailable(command)) {
return command;
}
}
return undefined;
}
/**
* Generate VS Code tasks.json for SCA integration
*/
static generateVSCodeTasks(outputPath = '.vscode/tasks.json') {
const tasksConfig = {
version: '2.0.0',
tasks: [
{
label: 'SCA: Analyze Current File',
type: 'shell',
command: 'sca',
args: ['file', '${file}', '--framework', 'nestjs'],
group: 'build',
presentation: {
echo: true,
reveal: 'always',
focus: false,
panel: 'shared'
},
problemMatcher: []
},
{
label: 'SCA: Analyze Project',
type: 'shell',
command: 'sca',
args: ['project', '${workspaceFolder}/src', '--format', 'html', '--output', 'reports/analysis.html'],
group: 'build',
presentation: {
echo: true,
reveal: 'always',
focus: false,
panel: 'shared'
},
problemMatcher: []
},
{
label: 'SCA: Generate HTML Report',
type: 'shell',
command: 'sca',
args: ['project', '${workspaceFolder}/src', '--format', 'html', '--output', 'reports/sca-report.html'],
group: 'build',
presentation: {
echo: true,
reveal: 'always',
focus: false,
panel: 'shared'
},
problemMatcher: []
}
]
};
// Ensure .vscode directory exists
const vscodeDirPath = path.dirname(outputPath);
if (!fs.existsSync(vscodeDirPath)) {
fs.mkdirSync(vscodeDirPath, { recursive: true });
}
fs.writeFileSync(outputPath, JSON.stringify(tasksConfig, null, 2));
console.log(`✅ Generated VS Code tasks at ${outputPath}`);
}
/**
* Open file in detected editor
*/
static openInEditor(filePath, lineNumber, editorConfig) {
const config = editorConfig || this.detectEditor();
const editor = config.detectedEditor || config.defaultEditor || 'code';
const editorInfo = this.EDITOR_COMMANDS[editor];
if (!editorInfo) {
console.warn(`⚠️ Unknown editor: ${editor}`);
return;
}
try {
const { spawn } = require('child_process');
let args = [...editorInfo.args];
if (lineNumber && editorInfo.supportsLineNumbers) {
const lineArg = filePath + editorInfo.lineNumberFormat.replace('line', lineNumber.toString());
args.push(lineArg);
}
else {
args.push(filePath);
}
spawn(editorInfo.command, args, { detached: true, stdio: 'ignore' });
console.log(`📝 Opening ${filePath} in ${editorInfo.name}${lineNumber ? ` at line ${lineNumber}` : ''}`);
}
catch (error) {
console.error(`❌ Failed to open editor: ${error}`);
}
}
}
exports.EditorDetector = EditorDetector;
//# sourceMappingURL=editor-detector.js.map