UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

283 lines (247 loc) 7.57 kB
/** * Platform Utilities (JavaScript wrapper) * * This is a JavaScript wrapper for the TypeScript platformUtils module. * It simulates the core functionality for use in JavaScript-only environments. */ const fs = require('fs'); const path = require('path'); const os = require('os'); // Line ending types const LINE_ENDINGS = { lf: '\n', crlf: '\r\n', auto: os.platform() === 'win32' ? '\r\n' : '\n' }; class PathUtils { // Normalize path separators for the current platform static normalizePath(filePath) { return filePath.replace(/[/\\]+/g, path.sep); } // Ensure a path uses forward slashes static forwardSlashes(filePath) { return filePath.replace(/\\/g, '/'); } // Convert a path to an absolute path static toAbsolutePath(filePath, basePath = process.cwd()) { if (path.isAbsolute(filePath)) { return this.normalizePath(filePath); } return this.normalizePath(path.resolve(basePath, filePath)); } // Get a relative path from one location to another static getRelativePath(from, to) { const relativePath = path.relative(from, to); return this.normalizePath(relativePath); } // Ensure a directory exists, creating it if necessary static ensureDir(dirPath) { try { if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } return true; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(`Error creating directory ${dirPath}: ${errorMessage}`); return false; } } // Get a platform-appropriate temporary directory path static getTempDir(subdir) { const tempBase = os.tmpdir(); const dirPath = subdir ? path.join(tempBase, subdir) : tempBase; this.ensureDir(dirPath); return dirPath; } // Determine if a path exists and is a directory static isDirectory(dirPath) { try { return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory(); } catch (error) { return false; } } // Determine if a path exists and is a file static isFile(filePath) { try { return fs.existsSync(filePath) && fs.statSync(filePath).isFile(); } catch (error) { return false; } } } class FileUtils { // Ensure file content has consistent line endings static normalizeLineEndings(content, lineEnding = 'auto') { // First convert all line endings to LF const normalized = content.replace(/\r\n|\r/g, '\n'); // Then convert to the desired line ending if (lineEnding === 'crlf') { return normalized.replace(/\n/g, '\r\n'); } if (lineEnding === 'auto') { return os.platform() === 'win32' ? normalized.replace(/\n/g, '\r\n') : normalized; } return normalized; } // Write file with consistent line endings static writeFile(filePath, content, lineEnding = 'auto') { try { // Ensure parent directory exists const dirPath = path.dirname(filePath); if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } // Normalize line endings const normalized = this.normalizeLineEndings(content, lineEnding); // Write to file fs.writeFileSync(filePath, normalized); return true; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(`Error writing file ${filePath}: ${errorMessage}`); return false; } } // Read file and normalize line endings static readFile(filePath, lineEnding = 'auto') { try { if (!fs.existsSync(filePath)) { return null; } const content = fs.readFileSync(filePath, 'utf8'); return this.normalizeLineEndings(content, lineEnding); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(`Error reading file ${filePath}: ${errorMessage}`); return null; } } } class TestOutputUtils { // Generate a platform-appropriate path for test outputs static getTestOutputPath(componentPath) { const filename = path.basename(componentPath, path.extname(componentPath)); return path.join('tests', filename, `${filename}.spec.ts`); } // Generate test configuration content with appropriate line endings static generateTestConfig(configType, outputDir, lineEnding = 'auto') { let content = ''; if (configType === 'playwright') { content = ` import { defineConfig } from '@playwright/test'; export default defineConfig({ testDir: './', outputDir: '../test-results', timeout: 30000, fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: [['html', { outputFolder: '../test-report' }]], use: { baseURL: process.env.BASE_URL || 'http://localhost:3000', trace: 'on-first-retry', screenshot: 'only-on-failure', }, projects: [ { name: 'chromium', use: { browserName: 'chromium' }, }, { name: 'firefox', use: { browserName: 'firefox' }, }, { name: 'webkit', use: { browserName: 'webkit' }, }, ], }); `.trim(); } else { content = ` module.exports = { preset: 'ts-jest', testEnvironment: 'jsdom', testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], moduleNameMapper: { '\\\\.(css|less|scss|sass)$': 'identity-obj-proxy', '^@/(.*)$': '<rootDir>/src/$1', }, collectCoverage: true, collectCoverageFrom: [ 'src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts', '!src/mocks/**', ], coverageDirectory: '../coverage', }; `.trim(); } return FileUtils.normalizeLineEndings(content, lineEnding); } } // Cross-platform shell utilities class ShellUtils { // Get platform-appropriate shell command static getCommand(command, args = []) { const isWindows = os.platform() === 'win32'; // Handle commands that need special treatment on Windows if (isWindows) { // Common commands that need to be mapped on Windows const windowsCommandMap = { 'rm': 'del', 'cp': 'copy', 'mv': 'move', 'ls': 'dir', 'cat': 'type', 'mkdir': 'md', 'rmdir': 'rd', 'touch': 'echo.>', 'grep': 'findstr' }; // Map command if needed const mappedCommand = windowsCommandMap[command] || command; // Build the command string return [mappedCommand, ...args].join(' '); } // For non-Windows platforms, just join the command and args return [command, ...args].join(' '); } // Get platform-appropriate file path for a command static getCommandPath(filePath) { const isWindows = os.platform() === 'win32'; // On Windows, wrap paths with spaces in quotes if (isWindows && filePath.includes(' ')) { return `"${filePath}"`; } // On Unix-like systems, escape spaces return filePath.replace(/ /g, '\\ '); } } // Get platform information function getPlatformInfo() { const platform = os.platform(); return { platform, isWindows: platform === 'win32', isMac: platform === 'darwin', isLinux: platform === 'linux', arch: os.arch(), pathSeparator: path.sep, lineEnding: platform === 'win32' ? '\r\n' : '\n' }; } module.exports = { LINE_ENDINGS, PathUtils, FileUtils, TestOutputUtils, ShellUtils, getPlatformInfo };