Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 2x 2x 2x 11x 11x 1x 10x 10x 10x 10x 10x 23x 9x 9x 9x 10x 2x 10x 1x 9x 9x 41x 1x 1x 9x 9x 27x 6x 6x 9x 9x 9x | import fs from 'fs-extra';
import path from 'path';
const FRAMEWORK_PATTERNS = {
'next.js': { dep: 'next', stack: 'next.js' },
'react': { dep: 'react', stack: 'react' },
'vite': { dep: 'vite', stack: 'vite' },
'express': { dep: 'express', stack: 'node-api' },
'nestjs': { dep: '@nestjs/core', stack: 'node-api' },
'fastify': { dep: 'fastify', stack: 'node-api' },
};
const TEST_RUNNER_PATTERNS = {
'jest': ['jest', '@types/jest'],
'vitest': ['vitest'],
'mocha': ['mocha'],
'jasmine': ['jasmine'],
};
const BUILD_TOOL_PATTERNS = {
'vite': ['vite'],
'webpack': ['webpack'],
'turbopack': ['next'], // Next.js uses Turbopack
'tsc': ['typescript'],
};
export async function detectNodeStack(cwd) {
const pkgPath = path.join(cwd, 'package.json');
if (!(await fs.pathExists(pkgPath))) {
return { detected: false };
}
const pkg = await fs.readJson(pkgPath);
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
// Detect framework
let framework = null;
let stack = null;
for (const [name, { dep, stack: stackName }] of Object.entries(FRAMEWORK_PATTERNS)) {
if (deps[dep]) {
framework = name;
stack = stackName;
break;
}
}
// Determine stack for react+vite
if (framework === 'react' && deps['vite']) {
stack = 'react-vite';
}
if (!framework) {
return { detected: false };
}
// Detect test runner
let testRunner = null;
for (const [runner, patterns] of Object.entries(TEST_RUNNER_PATTERNS)) {
if (patterns.some(p => deps[p])) {
testRunner = runner;
break;
}
}
// Detect build tool
let buildTool = null;
for (const [tool, patterns] of Object.entries(BUILD_TOOL_PATTERNS)) {
if (patterns.some(p => deps[p])) {
buildTool = tool;
break;
}
}
// Detect linter/formatter
const linter = deps['eslint'] ? 'eslint' : null;
const formatter = deps['prettier'] ? 'prettier' : null;
return {
detected: true,
stack,
confidence: 'high',
language: deps['typescript'] ? 'typescript' : 'javascript',
framework,
testRunner,
linter,
formatter,
buildTool,
evidence: {
files: ['package.json'],
dependencies: Object.keys(deps).slice(0, 5),
scripts: pkg.scripts || {},
},
};
} |