es-guard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/cli.js +95 -0
- package/dist/lib/checkCompatiblity.js +34 -0
- package/dist/lib/createESLintConfig.js +36 -0
- package/dist/lib/getBrowserTargets.js +79 -0
- package/dist/lib/isValidEcmaVersion.js +13 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/validateConfig.js +9 -0
- package/dist/lib/walkDir.js +22 -0
- package/package.json +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Max Kayander
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# ES-Guard
|
|
2
|
+
|
|
3
|
+
[](https://codecov.io/gh/mkayander/es-guard)
|
|
4
|
+
|
|
5
|
+
A TypeScript-based tool to check JavaScript compatibility with target environments using ESLint.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🔍 **ES Version Compatibility**: Check if your JavaScript code is compatible with specific ES versions (ES2015, ES2016, ES2017, etc.)
|
|
10
|
+
- 🌐 **Browser Compatibility**: Verify browser support using eslint-plugin-compat
|
|
11
|
+
- 🎯 **Auto Browser Detection**: Automatically determine browser targets from ES version (optional)
|
|
12
|
+
- 📁 **Directory Scanning**: Automatically scan directories for JavaScript files
|
|
13
|
+
- 🎯 **GitHub Actions Ready**: Works seamlessly with GitHub Actions
|
|
14
|
+
- 📦 **NPM Package**: Install globally or use as a dependency
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
### Global Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g es-guard
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Local Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install --save-dev es-guard
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### From Source
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/mkayander/es-guard.git
|
|
34
|
+
cd es-guard
|
|
35
|
+
npm install
|
|
36
|
+
npm run build
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Command Line
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Basic usage with defaults (auto-determined browsers)
|
|
45
|
+
es-guard
|
|
46
|
+
|
|
47
|
+
# Check specific directory
|
|
48
|
+
es-guard build
|
|
49
|
+
|
|
50
|
+
# Specify target ES version (year format)
|
|
51
|
+
es-guard -t 2020 build
|
|
52
|
+
|
|
53
|
+
# Specify target ES version (numeric format)
|
|
54
|
+
es-guard -t 11 build
|
|
55
|
+
|
|
56
|
+
# Use latest ES version
|
|
57
|
+
es-guard -t latest build
|
|
58
|
+
|
|
59
|
+
# Specify custom browser targets
|
|
60
|
+
es-guard --browsers "> 0.5%, last 2 versions, Firefox ESR, not dead" dist
|
|
61
|
+
|
|
62
|
+
# Show help
|
|
63
|
+
es-guard --help
|
|
64
|
+
|
|
65
|
+
# Show version
|
|
66
|
+
es-guard --version
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Programmatic Usage
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { checkCompatibility } from "es-guard";
|
|
73
|
+
|
|
74
|
+
// With auto-determined browsers
|
|
75
|
+
const violations = await checkCompatibility({
|
|
76
|
+
dir: "dist",
|
|
77
|
+
target: "2015",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// With custom browsers
|
|
81
|
+
const violations = await checkCompatibility({
|
|
82
|
+
dir: "dist",
|
|
83
|
+
target: "2015",
|
|
84
|
+
browsers: "> 1%, last 2 versions, not dead, ie 11",
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### GitHub Actions
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
name: Check Compatibility
|
|
92
|
+
on: [push, pull_request]
|
|
93
|
+
|
|
94
|
+
jobs:
|
|
95
|
+
compatibility:
|
|
96
|
+
runs-on: ubuntu-latest
|
|
97
|
+
steps:
|
|
98
|
+
- uses: actions/checkout@v3
|
|
99
|
+
- uses: actions/setup-node@v3
|
|
100
|
+
with:
|
|
101
|
+
node-version: "18"
|
|
102
|
+
- run: npm install
|
|
103
|
+
- run: npm run build
|
|
104
|
+
- run: npx es-guard -t 2015 dist
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Configuration
|
|
108
|
+
|
|
109
|
+
### Parameters
|
|
110
|
+
|
|
111
|
+
| Parameter | Description | Default | Required |
|
|
112
|
+
| ---------- | ------------------------------------------ | --------------------------- | -------- |
|
|
113
|
+
| `path` | Directory to scan for JavaScript files | `dist` | No |
|
|
114
|
+
| `target` | Target ES version | `2015` | Yes |
|
|
115
|
+
| `browsers` | Browser targets for compatibility checking | Auto-determined from target | No |
|
|
116
|
+
|
|
117
|
+
### ES Target Versions
|
|
118
|
+
|
|
119
|
+
The `target` parameter accepts multiple formats:
|
|
120
|
+
|
|
121
|
+
- **Year format**: `2015`, `2016`, `2017`, etc.
|
|
122
|
+
- **Numeric format**: `6` (ES2015), `7` (ES2016), `11` (ES2020), etc.
|
|
123
|
+
- **Latest**: `latest` for the most recent ES version
|
|
124
|
+
|
|
125
|
+
### Browser Targets
|
|
126
|
+
|
|
127
|
+
The `browsers` parameter uses the same format as Browserslist. If not specified, browsers will be automatically determined based on the ES target:
|
|
128
|
+
|
|
129
|
+
- **ES2015/ES6**: `> 1%, last 2 versions, not dead, ie 11`
|
|
130
|
+
- **ES2016-2017/ES7-8**: `> 1%, last 2 versions, not dead, not ie 11`
|
|
131
|
+
- **ES2018-2019/ES9-10**: `> 1%, last 2 versions, not dead, not ie 11, not op_mini all`
|
|
132
|
+
- **ES2020+/ES11+**: `> 1%, last 2 versions, not dead, not ie 11, not op_mini all, not android < 67`
|
|
133
|
+
|
|
134
|
+
Custom browser targets examples:
|
|
135
|
+
|
|
136
|
+
- `> 1%, last 2 versions, not dead, ie 11` - Modern browsers + IE11
|
|
137
|
+
- `> 0.5%, last 2 versions, Firefox ESR, not dead` - Broader support
|
|
138
|
+
- `defaults` - Default Browserslist targets
|
|
139
|
+
- `last 1 version` - Latest version of each browser
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
### Setup
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm install
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Build
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm run build
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Development Mode
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm run dev
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Testing
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npm test
|
|
165
|
+
npm run test:run
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Linting
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npm run lint
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Publishing to NPM
|
|
175
|
+
|
|
176
|
+
1. Update the version in `package.json`
|
|
177
|
+
2. Update the repository URL in `package.json`
|
|
178
|
+
3. Build the project: `npm run build`
|
|
179
|
+
4. Publish: `npm publish`
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
184
|
+
|
|
185
|
+
## Contributing
|
|
186
|
+
|
|
187
|
+
1. Fork the repository
|
|
188
|
+
2. Create a feature branch
|
|
189
|
+
3. Make your changes
|
|
190
|
+
4. Add tests if applicable
|
|
191
|
+
5. Run the linter: `npm run lint`
|
|
192
|
+
6. Submit a pull request
|
|
193
|
+
|
|
194
|
+
## Support
|
|
195
|
+
|
|
196
|
+
- 📖 [Documentation](https://github.com/mkayander/es-guard#readme)
|
|
197
|
+
- 🐛 [Issues](https://github.com/mkayander/es-guard/issues)
|
|
198
|
+
- 💬 [Discussions](https://github.com/mkayander/es-guard/discussions)
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
5
|
+
import { checkCompatibility } from "./lib/checkCompatiblity.js";
|
|
6
|
+
import { getBrowserTargetsFromString } from "./lib/getBrowserTargets.js";
|
|
7
|
+
const version = packageJson.version;
|
|
8
|
+
// Create the main program
|
|
9
|
+
const program = new Command();
|
|
10
|
+
// Configure the program
|
|
11
|
+
program
|
|
12
|
+
.name("es-guard")
|
|
13
|
+
.description("JavaScript Compatibility Checker - Check if your JavaScript code is compatible with target environments")
|
|
14
|
+
.version(version)
|
|
15
|
+
.argument("[directory]", "Directory to scan for JavaScript files", "dist")
|
|
16
|
+
.option("-t, --target <version>", "Target ES version (2015, 2016, 2017, etc. or 6, 7, 8, etc. or 'latest')", "2015")
|
|
17
|
+
.option("-b, --browsers <targets>", "Browser targets for compatibility checking (optional: auto-determined from target)")
|
|
18
|
+
.addHelpText("after", `
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
es-guard # Check 'dist' directory with ES2015 (auto-determined browsers)
|
|
22
|
+
es-guard build # Check 'build' directory with ES2015 (auto-determined browsers)
|
|
23
|
+
es-guard -t 2020 build # Check 'build' directory with ES2020 (auto-determined browsers)
|
|
24
|
+
es-guard -t 6 build # Check 'build' directory with ES6 (auto-determined browsers)
|
|
25
|
+
es-guard -t latest build # Check 'build' directory with latest ES (auto-determined browsers)
|
|
26
|
+
es-guard --target 2017 --browsers "> 0.5%, last 2 versions" dist
|
|
27
|
+
|
|
28
|
+
Browser targets use Browserslist format:
|
|
29
|
+
- If not specified, browsers will be auto-determined from the ES target version
|
|
30
|
+
- "> 1%, last 2 versions, not dead, ie 11" (for ES2015/ES6)
|
|
31
|
+
- "> 1%, last 2 versions, not dead, not ie 11" (for ES2016-2017/ES7-8)
|
|
32
|
+
- "> 1%, last 2 versions, not dead, not ie 11, not op_mini all" (for ES2018-2019/ES9-10)
|
|
33
|
+
- "> 1%, last 2 versions, not dead, not ie 11, not op_mini all, not android < 67" (for ES2020+/ES11+)
|
|
34
|
+
|
|
35
|
+
Exit codes:
|
|
36
|
+
0 - No compatibility issues found
|
|
37
|
+
1 - Compatibility issues found or error occurred
|
|
38
|
+
`);
|
|
39
|
+
// Add validation for the target option
|
|
40
|
+
program.hook("preAction", (thisCommand) => {
|
|
41
|
+
const options = thisCommand.opts();
|
|
42
|
+
const target = options.target;
|
|
43
|
+
// Validate ES target format - accept year format (YYYY), numeric format (N), or "latest"
|
|
44
|
+
if (!/^\d{4}$/.test(target) && !/^\d+$/.test(target) && target !== "latest") {
|
|
45
|
+
console.error(`Error: Invalid ES target: "${target}". Expected format: YYYY (e.g., 2015, 2020), numeric (e.g., 6, 11), or "latest"`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// Main action
|
|
50
|
+
program.action(async (directory, options) => {
|
|
51
|
+
try {
|
|
52
|
+
// Validate directory exists
|
|
53
|
+
if (!fs.existsSync(directory)) {
|
|
54
|
+
console.error(`Error: Directory "${directory}" does not exist`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const stat = fs.statSync(directory);
|
|
58
|
+
if (!stat.isDirectory()) {
|
|
59
|
+
console.error(`Error: "${directory}" is not a directory`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
// Determine browser targets
|
|
63
|
+
const browserTargets = options.browsers || getBrowserTargetsFromString(options.target);
|
|
64
|
+
console.log(`🔍 ES-Guard v${version}`);
|
|
65
|
+
console.log(`📁 Scanning directory: ${directory}`);
|
|
66
|
+
console.log(`🎯 Target ES version: ${options.target}`);
|
|
67
|
+
console.log(`🌐 Browser targets: ${browserTargets}${options.browsers ? "" : " (auto-determined)"}`);
|
|
68
|
+
console.log("");
|
|
69
|
+
const violations = await checkCompatibility({
|
|
70
|
+
dir: directory,
|
|
71
|
+
target: options.target,
|
|
72
|
+
browsers: browserTargets,
|
|
73
|
+
});
|
|
74
|
+
if (violations.length > 0) {
|
|
75
|
+
console.error(`❌ Found ${violations.length} file(s) with compatibility issues:`);
|
|
76
|
+
for (const violation of violations) {
|
|
77
|
+
console.error(`\n📄 ${violation.file}:`);
|
|
78
|
+
for (const message of violation.messages) {
|
|
79
|
+
console.error(` ${message.line}:${message.column} - ${message.message} (${message.ruleId})`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.log("✅ No compatibility issues found!");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
90
|
+
console.error(`❌ Error: ${message}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// Parse command line arguments
|
|
95
|
+
program.parse();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ESLint } from "eslint";
|
|
2
|
+
import { createESLintConfig } from "./createESLintConfig.js";
|
|
3
|
+
import { walkDir } from "./walkDir.js";
|
|
4
|
+
export const checkCompatibility = async (config) => {
|
|
5
|
+
const jsFiles = walkDir(config.dir);
|
|
6
|
+
if (jsFiles.length === 0) {
|
|
7
|
+
console.log(`No JavaScript files found in directory: ${config.dir}`);
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const eslint = new ESLint(createESLintConfig(config.target, config.browsers));
|
|
11
|
+
const violations = [];
|
|
12
|
+
for (const file of jsFiles) {
|
|
13
|
+
try {
|
|
14
|
+
const results = await eslint.lintFiles([file]);
|
|
15
|
+
if (Array.isArray(results)) {
|
|
16
|
+
for (const result of results) {
|
|
17
|
+
if (result.messages.length > 0) {
|
|
18
|
+
violations.push({
|
|
19
|
+
file: result.filePath,
|
|
20
|
+
messages: result.messages,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.warn(`Warning: ESLint did not return an array for file ${file}.`, results);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.warn(`Warning: Could not lint file ${file}:`, error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return violations;
|
|
34
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import compat from "eslint-plugin-compat";
|
|
2
|
+
import { getBrowserTargetsFromString, parseEcmaVersion } from "./getBrowserTargets.js";
|
|
3
|
+
import { isValidEcmaVersion } from "./isValidEcmaVersion.js";
|
|
4
|
+
const getEcmaVersion = (target) => {
|
|
5
|
+
const ecmaVersion = parseEcmaVersion(target);
|
|
6
|
+
if (!isValidEcmaVersion(ecmaVersion)) {
|
|
7
|
+
throw new Error(`Invalid ECMAScript version: ${ecmaVersion}. Target year ${target} is not supported.`);
|
|
8
|
+
}
|
|
9
|
+
return ecmaVersion;
|
|
10
|
+
};
|
|
11
|
+
export const createESLintConfig = (target, browsers) => {
|
|
12
|
+
// Convert target year to ECMAScript version number using the validation function
|
|
13
|
+
const ecmaVersion = getEcmaVersion(target);
|
|
14
|
+
// Use provided browsers or auto-determine from target
|
|
15
|
+
const browserTargets = browsers || getBrowserTargetsFromString(target);
|
|
16
|
+
return {
|
|
17
|
+
overrideConfigFile: true,
|
|
18
|
+
overrideConfig: [
|
|
19
|
+
{
|
|
20
|
+
plugins: {
|
|
21
|
+
compat,
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
"compat/compat": "error",
|
|
25
|
+
},
|
|
26
|
+
languageOptions: {
|
|
27
|
+
ecmaVersion: ecmaVersion,
|
|
28
|
+
sourceType: "module",
|
|
29
|
+
},
|
|
30
|
+
settings: {
|
|
31
|
+
browsers: browserTargets,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a string target to Linter.EcmaVersion type.
|
|
3
|
+
* Handles year format (2015), numeric format (6), and "latest".
|
|
4
|
+
* Returns null for unknown values to indicate they should use default.
|
|
5
|
+
*/
|
|
6
|
+
export const parseEcmaVersion = (target) => {
|
|
7
|
+
// Handle "latest"
|
|
8
|
+
if (target === "latest") {
|
|
9
|
+
return "latest";
|
|
10
|
+
}
|
|
11
|
+
const num = parseInt(target);
|
|
12
|
+
// Handle year format (2015, 2016, etc.)
|
|
13
|
+
if (num >= 2015 && num <= 2026) {
|
|
14
|
+
return num;
|
|
15
|
+
}
|
|
16
|
+
// Handle numeric format (3, 5, 6, 7, etc.)
|
|
17
|
+
if (num >= 3 && num <= 17) {
|
|
18
|
+
return num;
|
|
19
|
+
}
|
|
20
|
+
// For unknown values, return null to indicate default should be used
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Maps ES target versions to appropriate browser targets for compatibility checking.
|
|
25
|
+
* This provides sensible defaults based on when ES features were widely supported.
|
|
26
|
+
*/
|
|
27
|
+
export const getBrowserTargets = (target) => {
|
|
28
|
+
switch (target) {
|
|
29
|
+
// Legacy versions
|
|
30
|
+
case 3:
|
|
31
|
+
return "> 0.1%, ie 6";
|
|
32
|
+
case 5:
|
|
33
|
+
return "> 0.5%, ie 8";
|
|
34
|
+
// ES2015 (ES6) - Conservative targets including IE11
|
|
35
|
+
case 6:
|
|
36
|
+
case 2015:
|
|
37
|
+
return "> 1%, last 2 versions, not dead, ie 11";
|
|
38
|
+
// ES2016-2017 (ES7-8) - Drop IE11 but keep other older browsers
|
|
39
|
+
case 7:
|
|
40
|
+
case 8:
|
|
41
|
+
case 2016:
|
|
42
|
+
case 2017:
|
|
43
|
+
return "> 1%, last 2 versions, not dead, not ie 11";
|
|
44
|
+
// ES2018-2019 (ES9-10) - More modern browsers
|
|
45
|
+
case 9:
|
|
46
|
+
case 10:
|
|
47
|
+
case 2018:
|
|
48
|
+
case 2019:
|
|
49
|
+
return "> 1%, last 2 versions, not dead, not ie 11, not op_mini all";
|
|
50
|
+
// ES2020+ (ES11+) - Latest browsers with good modern JS support
|
|
51
|
+
case 11:
|
|
52
|
+
case 12:
|
|
53
|
+
case 13:
|
|
54
|
+
case 14:
|
|
55
|
+
case 15:
|
|
56
|
+
case 16:
|
|
57
|
+
case 17:
|
|
58
|
+
case 2020:
|
|
59
|
+
case 2021:
|
|
60
|
+
case 2022:
|
|
61
|
+
case 2023:
|
|
62
|
+
case 2024:
|
|
63
|
+
case 2025:
|
|
64
|
+
case 2026:
|
|
65
|
+
case "latest":
|
|
66
|
+
return "> 1%, last 2 versions, not dead, not ie 11, not op_mini all, not android < 67";
|
|
67
|
+
// Default fallback for unknown versions
|
|
68
|
+
default:
|
|
69
|
+
return "> 1%, last 2 versions, not dead";
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Convenience function that combines parsing and browser target determination.
|
|
74
|
+
* Accepts string input and returns appropriate browser targets.
|
|
75
|
+
*/
|
|
76
|
+
export const getBrowserTargetsFromString = (target) => {
|
|
77
|
+
const ecmaVersion = parseEcmaVersion(target);
|
|
78
|
+
return getBrowserTargets(ecmaVersion);
|
|
79
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const validVersions = new Set([
|
|
2
|
+
3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025,
|
|
3
|
+
2026,
|
|
4
|
+
]);
|
|
5
|
+
export const isValidEcmaVersion = (ecmaVersion) => {
|
|
6
|
+
if (!ecmaVersion) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
if (typeof ecmaVersion === "string") {
|
|
10
|
+
return ecmaVersion === "latest";
|
|
11
|
+
}
|
|
12
|
+
return validVersions.has(ecmaVersion);
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
export const validateConfig = (config) => {
|
|
3
|
+
if (!fs.existsSync(config.dir)) {
|
|
4
|
+
throw new Error(`Output directory "${config.dir}" does not exist. Please build the project first.`);
|
|
5
|
+
}
|
|
6
|
+
if (!config.target) {
|
|
7
|
+
throw new Error("Target ES version is required");
|
|
8
|
+
}
|
|
9
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
export const walkDir = (dir) => {
|
|
4
|
+
const files = [];
|
|
5
|
+
try {
|
|
6
|
+
const entries = fs.readdirSync(dir);
|
|
7
|
+
for (const entry of entries) {
|
|
8
|
+
const fullPath = path.join(dir, entry);
|
|
9
|
+
const stat = fs.statSync(fullPath);
|
|
10
|
+
if (stat.isDirectory()) {
|
|
11
|
+
files.push(...walkDir(fullPath));
|
|
12
|
+
}
|
|
13
|
+
else if (fullPath.endsWith(".js")) {
|
|
14
|
+
files.push(fullPath);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.warn(`Warning: Could not read directory ${dir}:`, error);
|
|
20
|
+
}
|
|
21
|
+
return files;
|
|
22
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "es-guard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A tool to check JavaScript compatibility with target environments",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/cli.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"es-guard": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"dev": "tsc --watch",
|
|
16
|
+
"start": "node dist/cli.js",
|
|
17
|
+
"test": "npm run build && vitest",
|
|
18
|
+
"test:run": "npm run build && vitest run",
|
|
19
|
+
"coverage": "vitest run --coverage",
|
|
20
|
+
"coverage:check": "vitest run --coverage --reporter=verbose",
|
|
21
|
+
"lint": "eslint src/**/*.ts",
|
|
22
|
+
"lint:check": "eslint src/**/*.ts --max-warnings 0",
|
|
23
|
+
"format": "prettier --write src/**/*.ts",
|
|
24
|
+
"format:check": "prettier --check src/**/*.ts",
|
|
25
|
+
"clean": "rimraf dist",
|
|
26
|
+
"prepublishOnly": "npm run clean && npm run build && npm run coverage:check",
|
|
27
|
+
"semantic-release": "semantic-release"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"javascript",
|
|
31
|
+
"compatibility",
|
|
32
|
+
"eslint",
|
|
33
|
+
"browser-support",
|
|
34
|
+
"es2015",
|
|
35
|
+
"es2016",
|
|
36
|
+
"es2017",
|
|
37
|
+
"es2018",
|
|
38
|
+
"es2019",
|
|
39
|
+
"es2020"
|
|
40
|
+
],
|
|
41
|
+
"author": "",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@actions/core": "^1.11.1",
|
|
45
|
+
"commander": "^14.0.0",
|
|
46
|
+
"eslint": "^9.30.1",
|
|
47
|
+
"eslint-plugin-compat": "^6.0.2"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@eslint/js": "^9.30.1",
|
|
51
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
52
|
+
"@semantic-release/git": "^10.0.1",
|
|
53
|
+
"@types/eslint": "^9.6.1",
|
|
54
|
+
"@types/node": "^20.19.4",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
|
56
|
+
"@typescript-eslint/parser": "^8.35.1",
|
|
57
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
58
|
+
"prettier": "^3.6.2",
|
|
59
|
+
"rimraf": "^6.0.1",
|
|
60
|
+
"semantic-release": "^24.2.6",
|
|
61
|
+
"typescript": "5.8.3",
|
|
62
|
+
"vitest": "^3.2.4"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=14.0.0"
|
|
66
|
+
},
|
|
67
|
+
"repository": {
|
|
68
|
+
"type": "git",
|
|
69
|
+
"url": "git+https://github.com/mkayander/es-guard.git"
|
|
70
|
+
},
|
|
71
|
+
"bugs": {
|
|
72
|
+
"url": "https://github.com/mkayander/es-guard/issues"
|
|
73
|
+
},
|
|
74
|
+
"homepage": "https://github.com/mkayander/es-guard#readme",
|
|
75
|
+
"packageManager": "pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184"
|
|
76
|
+
}
|