Detect Plugin
Automatically detect the minimum required ES version for your code
Overview
The Detect plugin automatically determines the minimum ECMAScript version required to run your JavaScript code. It analyzes all ES features in your code and returns the lowest ES version that supports all detected features.
Installation & Import
import detectPlugin from 'fast-brake/src/plugins/detect';
// Use with detector
const detector = new Detector({ plugins: [detectPlugin] });
How It Works
The Detect plugin:
- Scans your code for all ES features
- Identifies the highest ES version feature used
- Returns the minimum ES version required
- Provides a complete feature inventory
Usage Examples
Basic Minimum Version Detection
import { getMinimumESVersion } from 'fast-brake';
const code = `
const arrow = () => {};
const template = \`Hello \${name}\`;
class MyClass {}
`;
const minVersion = await getMinimumESVersion(code);
console.log(minVersion); // 'es2015'
Detailed Feature Analysis
import { Detector } from 'fast-brake';
import detectPlugin from 'fast-brake/src/plugins/detect';
const detector = new Detector({ plugins: [detectPlugin] });
await detector.initialize();
const code = `
// ES2015 features
const arrow = () => {};
// ES2017 features
async function getData() {
await fetch('/api');
}
// ES2020 features
const value = obj?.prop ?? 'default';
`;
const analysis = await detector.detect(code);
// Group features by version
const featuresByVersion = {};
analysis.forEach(feature => {
if (!featuresByVersion[feature.version]) {
featuresByVersion[feature.version] = [];
}
featuresByVersion[feature.version].push(feature.name);
});
console.log('Features by ES version:', featuresByVersion);
// {
// es2015: ['arrow_functions', 'const'],
// es2017: ['async_functions', 'await'],
// es2020: ['optional_chaining', 'nullish_coalescing']
// }
console.log('Minimum required version:', 'es2020');
Common Use Cases
Dynamic Transpilation
import { getMinimumESVersion } from 'fast-brake';
import * as babel from '@babel/core';
async function smartTranspile(code, targetVersion = 'es5') {
const minVersion = await getMinimumESVersion(code);
// Skip transpilation if already compatible
if (compareVersions(minVersion, targetVersion) <= 0) {
console.log(`Code is already ${targetVersion} compatible`);
return code;
}
// Only transpile what's needed
const result = babel.transformSync(code, {
presets: [
['@babel/preset-env', {
targets: { esmodules: targetVersion === 'es2015' }
}]
]
});
return result.code;
}
Build Optimization
// webpack.config.js
const { getMinimumESVersion } = require('fast-brake');
module.exports = async (env, argv) => {
// Analyze entry point
const entryCode = fs.readFileSync('./src/index.js', 'utf-8');
const minVersion = await getMinimumESVersion(entryCode);
console.log(`Project requires minimum ${minVersion}`);
return {
entry: './src/index.js',
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: minVersion === 'es5' ? [] : ['babel-loader']
}]
},
optimization: {
// Skip optimization for modern code
minimize: minVersion !== 'es2020'
}
};
};
Polyfill Detection
import { getMinimumESVersion } from 'fast-brake';
const polyfillMap = {
es2015: ['promise-polyfill'],
es2017: ['async-polyfill'],
es2018: ['async-iteration-polyfill'],
es2019: ['array-flat-polyfill'],
es2020: ['optional-chaining-polyfill'],
es2021: ['string-replaceall-polyfill'],
es2022: ['array-at-polyfill']
};
async function getRequiredPolyfills(code) {
const minVersion = await getMinimumESVersion(code);
const polyfills = [];
// Collect all polyfills needed up to the min version
for (const [version, versionPolyfills] of Object.entries(polyfillMap)) {
if (compareVersions(version, minVersion) <= 0) {
polyfills.push(...versionPolyfills);
}
}
return polyfills;
}
// Usage
const code = readFileSync('app.js', 'utf-8');
const polyfills = await getRequiredPolyfills(code);
console.log('Required polyfills:', polyfills);
Version Comparison
Helper Functions
// Compare ES versions
function compareVersions(a, b) {
const versions = ['es5', 'es2015', 'es2016', 'es2017', 'es2018',
'es2019', 'es2020', 'es2021', 'es2022', 'es2023',
'es2024', 'es2025'];
return versions.indexOf(a) - versions.indexOf(b);
}
// Check if code requires transpilation
async function needsTranspilation(code, target) {
const minVersion = await getMinimumESVersion(code);
return compareVersions(minVersion, target) > 0;
}
// Get transpilation preset
async function getTranspilationPreset(code) {
const minVersion = await getMinimumESVersion(code);
const presets = {
es5: '@babel/preset-env',
es2015: '@babel/preset-es2015',
es2017: '@babel/preset-es2017',
// ... etc
};
return presets[minVersion] || '@babel/preset-env';
}
Integration Examples
With ESLint
// .eslintrc.js
const { getMinimumESVersion } = require('fast-brake');
module.exports = async () => {
// Detect project's ES version
const files = glob.sync('src/**/*.js');
let projectMinVersion = 'es5';
for (const file of files) {
const code = fs.readFileSync(file, 'utf-8');
const fileVersion = await getMinimumESVersion(code);
if (compareVersions(fileVersion, projectMinVersion) > 0) {
projectMinVersion = fileVersion;
}
}
// Configure ESLint based on detected version
return {
parserOptions: {
ecmaVersion: getEcmaVersion(projectMinVersion)
},
env: {
es6: projectMinVersion !== 'es5'
}
};
};
With Package.json
// update-engines.js
import { getMinimumESVersion } from 'fast-brake';
import { glob } from 'glob';
import fs from 'fs';
async function updateEngines() {
const files = glob.sync('src/**/*.js');
let maxVersion = 'es5';
for (const file of files) {
const code = fs.readFileSync(file, 'utf-8');
const version = await getMinimumESVersion(code);
if (compareVersions(version, maxVersion) > 0) {
maxVersion = version;
}
}
// Map ES version to Node.js version
const nodeVersionMap = {
es5: '0.10',
es2015: '6.0',
es2017: '8.0',
es2018: '10.0',
es2019: '12.0',
es2020: '14.0',
es2021: '15.0',
es2022: '16.0'
};
// Update package.json
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
pkg.engines = {
node: `>=${nodeVersionMap[maxVersion] || '14.0'}`
};
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
console.log(`Updated engines to Node.js ${nodeVersionMap[maxVersion]}+ for ${maxVersion}`);
}
Performance Considerations
Caching Results
const versionCache = new Map();
async function getCachedMinVersion(code) {
const hash = createHash('md5').update(code).digest('hex');
if (versionCache.has(hash)) {
return versionCache.get(hash);
}
const version = await getMinimumESVersion(code);
versionCache.set(hash, version);
return version;
}
Batch Processing
async function analyzeCodebase(directory) {
const files = glob.sync(`${directory}/**/*.js`);
const results = new Map();
// Process in parallel for performance
const analyses = await Promise.all(
files.map(async file => {
const code = fs.readFileSync(file, 'utf-8');
const version = await getMinimumESVersion(code);
return { file, version };
})
);
// Aggregate results
analyses.forEach(({ file, version }) => {
if (!results.has(version)) {
results.set(version, []);
}
results.get(version).push(file);
});
return results;
}
Output Format
The Detect plugin returns the minimum ES version as a string:
// Possible return values
'es5' // No modern features detected
'es2015' // ES6 features (arrow functions, classes, etc.)
'es2016' // Exponentiation operator
'es2017' // Async/await
'es2018' // Rest/spread properties
'es2019' // Array.flat, Array.flatMap
'es2020' // Optional chaining, nullish coalescing
'es2021' // Logical assignment operators
'es2022' // Private fields, top-level await
'es2023' // Array methods (findLast, toSorted, etc.)
'es2024' // Promise.withResolvers, Object.groupBy
'es2025' // Temporal API, Set methods